playlist-data-engine 1.5.4 → 1.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/playlist-data-engine.js +1 -1
- package/dist/playlist-data-engine.mjs +237 -237
- package/package.json +1 -1
|
@@ -46,7 +46,7 @@ ${E.map(t=>` - ${t}`).join(`
|
|
|
46
46
|
|
|
47
47
|
`)}n.write("payload.value = newResult;"),n.write("return payload;");const h=n.compile();return(w,y)=>h(s,w,y)};let E;const i=wi,e=!cl.jitless,C=e&&Gp.value,o=A.catchall;let t;g._zod.parse=(s,n)=>{t??(t=I.value);const r=s.value;return i(r)?e&&C&&n?.async===!1&&n.jitless!==!0?(E||(E=Q(A.shape)),s=E(s,n),o?Nl([],r,s,n,t,g):s):B(s,n):(s.issues.push({expected:"object",code:"invalid_type",input:r,inst:g}),s)}});function Wl(g,A,B,I){for(const E of g)if(E.issues.length===0)return A.value=E.value,A;const Q=g.filter(E=>!kI(E));return Q.length===1?(A.value=Q[0].value,Q[0]):(A.issues.push({code:"invalid_union",input:A.value,inst:B,errors:g.map(E=>E.issues.map(i=>fg(i,I,pg())))}),A)}const gU=Z("$ZodUnion",(g,A)=>{pA.init(g,A),lA(g._zod,"optin",()=>A.options.some(Q=>Q._zod.optin==="optional")?"optional":void 0),lA(g._zod,"optout",()=>A.options.some(Q=>Q._zod.optout==="optional")?"optional":void 0),lA(g._zod,"values",()=>{if(A.options.every(Q=>Q._zod.values))return new Set(A.options.flatMap(Q=>Array.from(Q._zod.values)))}),lA(g._zod,"pattern",()=>{if(A.options.every(Q=>Q._zod.pattern)){const Q=A.options.map(E=>E._zod.pattern);return new RegExp(`^(${Q.map(E=>JC(E.source)).join("|")})$`)}});const B=A.options.length===1,I=A.options[0]._zod.run;g._zod.parse=(Q,E)=>{if(B)return I(Q,E);let i=!1;const e=[];for(const a of A.options){const C=a._zod.run({value:Q.value,issues:[]},E);if(C instanceof Promise)e.push(C),i=!0;else{if(C.issues.length===0)return C;e.push(C)}}return i?Promise.all(e).then(a=>Wl(a,Q,g,E)):Wl(e,Q,g,E)}}),IU=Z("$ZodIntersection",(g,A)=>{pA.init(g,A),g._zod.parse=(B,I)=>{const Q=B.value,E=A.left._zod.run({value:Q,issues:[]},I),i=A.right._zod.run({value:Q,issues:[]},I);return E instanceof Promise||i instanceof Promise?Promise.all([E,i]).then(([a,C])=>Hl(B,a,C)):Hl(B,E,i)}});function vC(g,A){if(g===A)return{valid:!0,data:g};if(g instanceof Date&&A instanceof Date&&+g==+A)return{valid:!0,data:g};if(fI(g)&&fI(A)){const B=Object.keys(A),I=Object.keys(g).filter(E=>B.indexOf(E)!==-1),Q={...g,...A};for(const E of I){const i=vC(g[E],A[E]);if(!i.valid)return{valid:!1,mergeErrorPath:[E,...i.mergeErrorPath]};Q[E]=i.data}return{valid:!0,data:Q}}if(Array.isArray(g)&&Array.isArray(A)){if(g.length!==A.length)return{valid:!1,mergeErrorPath:[]};const B=[];for(let I=0;I<g.length;I++){const Q=g[I],E=A[I],i=vC(Q,E);if(!i.valid)return{valid:!1,mergeErrorPath:[I,...i.mergeErrorPath]};B.push(i.data)}return{valid:!0,data:B}}return{valid:!1,mergeErrorPath:[]}}function Hl(g,A,B){const I=new Map;let Q;for(const e of A.issues)if(e.code==="unrecognized_keys"){Q??(Q=e);for(const a of e.keys)I.has(a)||I.set(a,{}),I.get(a).l=!0}else g.issues.push(e);for(const e of B.issues)if(e.code==="unrecognized_keys")for(const a of e.keys)I.has(a)||I.set(a,{}),I.get(a).r=!0;else g.issues.push(e);const E=[...I].filter(([,e])=>e.l&&e.r).map(([e])=>e);if(E.length&&Q&&g.issues.push({...Q,keys:E}),kI(g))return g;const i=vC(A.value,B.value);if(!i.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(i.mergeErrorPath)}`);return g.value=i.data,g}const QU=Z("$ZodRecord",(g,A)=>{pA.init(g,A),g._zod.parse=(B,I)=>{const Q=B.value;if(!fI(Q))return B.issues.push({expected:"record",code:"invalid_type",input:Q,inst:g}),B;const E=[],i=A.keyType._zod.values;if(i){B.value={};const e=new Set;for(const C of i)if(typeof C=="string"||typeof C=="number"||typeof C=="symbol"){e.add(typeof C=="number"?C.toString():C);const o=A.valueType._zod.run({value:Q[C],issues:[]},I);o instanceof Promise?E.push(o.then(t=>{t.issues.length&&B.issues.push(...ZI(C,t.issues)),B.value[C]=t.value})):(o.issues.length&&B.issues.push(...ZI(C,o.issues)),B.value[C]=o.value)}let a;for(const C in Q)e.has(C)||(a=a??[],a.push(C));a&&a.length>0&&B.issues.push({code:"unrecognized_keys",input:Q,inst:g,keys:a})}else{B.value={};for(const e of Reflect.ownKeys(Q)){if(e==="__proto__")continue;let a=A.keyType._zod.run({value:e,issues:[]},I);if(a instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if(typeof e=="string"&&Sl.test(e)&&a.issues.length){const t=A.keyType._zod.run({value:Number(e),issues:[]},I);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[e]=Q[e]:B.issues.push({code:"invalid_key",origin:"record",issues:a.issues.map(t=>fg(t,I,pg())),input:e,path:[e],inst:g});continue}const o=A.valueType._zod.run({value:Q[e],issues:[]},I);o instanceof Promise?E.push(o.then(t=>{t.issues.length&&B.issues.push(...ZI(e,t.issues)),B.value[a.value]=t.value})):(o.issues.length&&B.issues.push(...ZI(e,o.issues)),B.value[a.value]=o.value)}}return E.length?Promise.all(E).then(()=>B):B}}),EU=Z("$ZodEnum",(g,A)=>{pA.init(g,A);const B=Gl(A.entries),I=new Set(B);g._zod.values=I,g._zod.pattern=new RegExp(`^(${B.filter(Q=>hp.has(typeof Q)).map(Q=>typeof Q=="string"?Fi(Q):Q.toString()).join("|")})$`),g._zod.parse=(Q,E)=>{const i=Q.value;return I.has(i)||Q.issues.push({code:"invalid_value",values:B,input:i,inst:g}),Q}}),iU=Z("$ZodTransform",(g,A)=>{pA.init(g,A),g._zod.parse=(B,I)=>{if(I.direction==="backward")throw new rl(g.constructor.name);const Q=A.transform(B.value,B);if(I.async)return(Q instanceof Promise?Q:Promise.resolve(Q)).then(i=>(B.value=i,B));if(Q instanceof Promise)throw new UI;return B.value=Q,B}});function Jl(g,A){return g.issues.length&&A===void 0?{issues:[],value:void 0}:g}const xl=Z("$ZodOptional",(g,A)=>{pA.init(g,A),g._zod.optin="optional",g._zod.optout="optional",lA(g._zod,"values",()=>A.innerType._zod.values?new Set([...A.innerType._zod.values,void 0]):void 0),lA(g._zod,"pattern",()=>{const B=A.innerType._zod.pattern;return B?new RegExp(`^(${JC(B.source)})?$`):void 0}),g._zod.parse=(B,I)=>{if(A.innerType._zod.optin==="optional"){const Q=A.innerType._zod.run(B,I);return Q instanceof Promise?Q.then(E=>Jl(E,B.value)):Jl(Q,B.value)}return B.value===void 0?B:A.innerType._zod.run(B,I)}}),eU=Z("$ZodExactOptional",(g,A)=>{xl.init(g,A),lA(g._zod,"values",()=>A.innerType._zod.values),lA(g._zod,"pattern",()=>A.innerType._zod.pattern),g._zod.parse=(B,I)=>A.innerType._zod.run(B,I)}),aU=Z("$ZodNullable",(g,A)=>{pA.init(g,A),lA(g._zod,"optin",()=>A.innerType._zod.optin),lA(g._zod,"optout",()=>A.innerType._zod.optout),lA(g._zod,"pattern",()=>{const B=A.innerType._zod.pattern;return B?new RegExp(`^(${JC(B.source)}|null)$`):void 0}),lA(g._zod,"values",()=>A.innerType._zod.values?new Set([...A.innerType._zod.values,null]):void 0),g._zod.parse=(B,I)=>B.value===null?B:A.innerType._zod.run(B,I)}),CU=Z("$ZodDefault",(g,A)=>{pA.init(g,A),g._zod.optin="optional",lA(g._zod,"values",()=>A.innerType._zod.values),g._zod.parse=(B,I)=>{if(I.direction==="backward")return A.innerType._zod.run(B,I);if(B.value===void 0)return B.value=A.defaultValue,B;const Q=A.innerType._zod.run(B,I);return Q instanceof Promise?Q.then(E=>ql(E,A)):ql(Q,A)}});function ql(g,A){return g.value===void 0&&(g.value=A.defaultValue),g}const oU=Z("$ZodPrefault",(g,A)=>{pA.init(g,A),g._zod.optin="optional",lA(g._zod,"values",()=>A.innerType._zod.values),g._zod.parse=(B,I)=>(I.direction==="backward"||B.value===void 0&&(B.value=A.defaultValue),A.innerType._zod.run(B,I))}),tU=Z("$ZodNonOptional",(g,A)=>{pA.init(g,A),lA(g._zod,"values",()=>{const B=A.innerType._zod.values;return B?new Set([...B].filter(I=>I!==void 0)):void 0}),g._zod.parse=(B,I)=>{const Q=A.innerType._zod.run(B,I);return Q instanceof Promise?Q.then(E=>Ll(E,g)):Ll(Q,g)}});function Ll(g,A){return!g.issues.length&&g.value===void 0&&g.issues.push({code:"invalid_type",expected:"nonoptional",input:g.value,inst:A}),g}const sU=Z("$ZodCatch",(g,A)=>{pA.init(g,A),lA(g._zod,"optin",()=>A.innerType._zod.optin),lA(g._zod,"optout",()=>A.innerType._zod.optout),lA(g._zod,"values",()=>A.innerType._zod.values),g._zod.parse=(B,I)=>{if(I.direction==="backward")return A.innerType._zod.run(B,I);const Q=A.innerType._zod.run(B,I);return Q instanceof Promise?Q.then(E=>(B.value=E.value,E.issues.length&&(B.value=A.catchValue({...B,error:{issues:E.issues.map(i=>fg(i,I,pg()))},input:B.value}),B.issues=[]),B)):(B.value=Q.value,Q.issues.length&&(B.value=A.catchValue({...B,error:{issues:Q.issues.map(E=>fg(E,I,pg()))},input:B.value}),B.issues=[]),B)}}),nU=Z("$ZodPipe",(g,A)=>{pA.init(g,A),lA(g._zod,"values",()=>A.in._zod.values),lA(g._zod,"optin",()=>A.in._zod.optin),lA(g._zod,"optout",()=>A.out._zod.optout),lA(g._zod,"propValues",()=>A.in._zod.propValues),g._zod.parse=(B,I)=>{if(I.direction==="backward"){const E=A.out._zod.run(B,I);return E instanceof Promise?E.then(i=>Si(i,A.in,I)):Si(E,A.in,I)}const Q=A.in._zod.run(B,I);return Q instanceof Promise?Q.then(E=>Si(E,A.out,I)):Si(Q,A.out,I)}});function Si(g,A,B){return g.issues.length?(g.aborted=!0,g):A._zod.run({value:g.value,issues:g.issues},B)}const rU=Z("$ZodReadonly",(g,A)=>{pA.init(g,A),lA(g._zod,"propValues",()=>A.innerType._zod.propValues),lA(g._zod,"values",()=>A.innerType._zod.values),lA(g._zod,"optin",()=>A.innerType?._zod?.optin),lA(g._zod,"optout",()=>A.innerType?._zod?.optout),g._zod.parse=(B,I)=>{if(I.direction==="backward")return A.innerType._zod.run(B,I);const Q=A.innerType._zod.run(B,I);return Q instanceof Promise?Q.then(Vl):Vl(Q)}});function Vl(g){return g.value=Object.freeze(g.value),g}const cU=Z("$ZodCustom",(g,A)=>{oB.init(g,A),pA.init(g,A),g._zod.parse=(B,I)=>B,g._zod.check=B=>{const I=B.value,Q=A.fn(I);if(Q instanceof Promise)return Q.then(E=>vl(E,B,I,g));vl(Q,B,I,g)}});function vl(g,A,B,I){if(!g){const Q={code:"custom",input:B,inst:I,path:[...I._zod.def.path??[]],continue:!I._zod.def.abort};I._zod.def.params&&(Q.params=I._zod.def.params),A.issues.push(xQ(Q))}}var Xl;class GU{constructor(){this._map=new WeakMap,this._idmap=new Map}add(A,...B){const I=B[0];return this._map.set(A,I),I&&typeof I=="object"&&"id"in I&&this._idmap.set(I.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 I={...this.get(B)??{}};delete I.id;const Q={...I,...this._map.get(A)};return Object.keys(Q).length?Q:void 0}return this._map.get(A)}has(A){return this._map.has(A)}}function hU(){return new GU}(Xl=globalThis).__zod_globalRegistry??(Xl.__zod_globalRegistry=hU());const qQ=globalThis.__zod_globalRegistry;function lU(g,A){return new g({type:"string",...gA(A)})}function DU(g,A){return new g({type:"string",format:"email",check:"string_format",abort:!1,...gA(A)})}function Kl(g,A){return new g({type:"string",format:"guid",check:"string_format",abort:!1,...gA(A)})}function dU(g,A){return new g({type:"string",format:"uuid",check:"string_format",abort:!1,...gA(A)})}function wU(g,A){return new g({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...gA(A)})}function FU(g,A){return new g({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...gA(A)})}function MU(g,A){return new g({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...gA(A)})}function RU(g,A){return new g({type:"string",format:"url",check:"string_format",abort:!1,...gA(A)})}function yU(g,A){return new g({type:"string",format:"emoji",check:"string_format",abort:!1,...gA(A)})}function uU(g,A){return new g({type:"string",format:"nanoid",check:"string_format",abort:!1,...gA(A)})}function mU(g,A){return new g({type:"string",format:"cuid",check:"string_format",abort:!1,...gA(A)})}function SU(g,A){return new g({type:"string",format:"cuid2",check:"string_format",abort:!1,...gA(A)})}function bU(g,A){return new g({type:"string",format:"ulid",check:"string_format",abort:!1,...gA(A)})}function pU(g,A){return new g({type:"string",format:"xid",check:"string_format",abort:!1,...gA(A)})}function YU(g,A){return new g({type:"string",format:"ksuid",check:"string_format",abort:!1,...gA(A)})}function UU(g,A){return new g({type:"string",format:"ipv4",check:"string_format",abort:!1,...gA(A)})}function fU(g,A){return new g({type:"string",format:"ipv6",check:"string_format",abort:!1,...gA(A)})}function kU(g,A){return new g({type:"string",format:"cidrv4",check:"string_format",abort:!1,...gA(A)})}function ZU(g,A){return new g({type:"string",format:"cidrv6",check:"string_format",abort:!1,...gA(A)})}function NU(g,A){return new g({type:"string",format:"base64",check:"string_format",abort:!1,...gA(A)})}function WU(g,A){return new g({type:"string",format:"base64url",check:"string_format",abort:!1,...gA(A)})}function HU(g,A){return new g({type:"string",format:"e164",check:"string_format",abort:!1,...gA(A)})}function JU(g,A){return new g({type:"string",format:"jwt",check:"string_format",abort:!1,...gA(A)})}function xU(g,A){return new g({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...gA(A)})}function qU(g,A){return new g({type:"string",format:"date",check:"string_format",...gA(A)})}function LU(g,A){return new g({type:"string",format:"time",check:"string_format",precision:null,...gA(A)})}function VU(g,A){return new g({type:"string",format:"duration",check:"string_format",...gA(A)})}function vU(g,A){return new g({type:"number",checks:[],...gA(A)})}function XU(g,A){return new g({type:"number",check:"number_format",abort:!1,format:"safeint",...gA(A)})}function KU(g,A){return new g({type:"boolean",...gA(A)})}function zU(g){return new g({type:"unknown"})}function TU(g,A){return new g({type:"never",...gA(A)})}function zl(g,A){return new pl({check:"less_than",...gA(A),value:g,inclusive:!1})}function XC(g,A){return new pl({check:"less_than",...gA(A),value:g,inclusive:!0})}function Tl(g,A){return new Yl({check:"greater_than",...gA(A),value:g,inclusive:!1})}function KC(g,A){return new Yl({check:"greater_than",...gA(A),value:g,inclusive:!0})}function Ol(g,A){return new oY({check:"multiple_of",...gA(A),value:g})}function jl(g,A){return new sY({check:"max_length",...gA(A),maximum:g})}function bi(g,A){return new nY({check:"min_length",...gA(A),minimum:g})}function Pl(g,A){return new rY({check:"length_equals",...gA(A),length:g})}function OU(g,A){return new cY({check:"string_format",format:"regex",...gA(A),pattern:g})}function jU(g){return new GY({check:"string_format",format:"lowercase",...gA(g)})}function PU(g){return new hY({check:"string_format",format:"uppercase",...gA(g)})}function _U(g,A){return new lY({check:"string_format",format:"includes",...gA(A),includes:g})}function $U(g,A){return new DY({check:"string_format",format:"starts_with",...gA(A),prefix:g})}function Af(g,A){return new dY({check:"string_format",format:"ends_with",...gA(A),suffix:g})}function NI(g){return new wY({check:"overwrite",tx:g})}function Bf(g){return NI(A=>A.normalize(g))}function gf(){return NI(g=>g.trim())}function If(){return NI(g=>g.toLowerCase())}function Qf(){return NI(g=>g.toUpperCase())}function Ef(){return NI(g=>cp(g))}function ef(g,A,B){return new g({type:"array",element:A,...gA(B)})}function af(g,A,B){return new g({type:"custom",check:"custom",fn:A,...gA(B)})}function Cf(g){const A=of(B=>(B.addIssue=I=>{if(typeof I=="string")B.issues.push(xQ(I,B.value,A._zod.def));else{const Q=I;Q.fatal&&(Q.continue=!1),Q.code??(Q.code="custom"),Q.input??(Q.input=B.value),Q.inst??(Q.inst=A),Q.continue??(Q.continue=!A._zod.def.abort),B.issues.push(xQ(Q))}},g(B.value,B)));return A}function of(g,A){const B=new oB({check:"custom",...gA(A)});return B._zod.check=g,B}function _l(g){let A=g?.target??"draft-2020-12";return A==="draft-4"&&(A="draft-04"),A==="draft-7"&&(A="draft-07"),{processors:g.processors??{},metadataRegistry:g?.metadata??qQ,target:A,unrepresentable:g?.unrepresentable??"throw",override:g?.override??(()=>{}),io:g?.io??"output",counter:0,seen:new Map,cycles:g?.cycles??"ref",reused:g?.reused??"inline",external:g?.external??void 0}}function HA(g,A,B={path:[],schemaPath:[]}){var I;const Q=g._zod.def,E=A.seen.get(g);if(E)return E.count++,B.schemaPath.includes(g)&&(E.cycle=B.path),E.schema;const i={schema:{},count:1,cycle:void 0,path:B.path};A.seen.set(g,i);const e=g._zod.toJSONSchema?.();if(e)i.schema=e;else{const o={...B,schemaPath:[...B.schemaPath,g],path:B.path};if(g._zod.processJSONSchema)g._zod.processJSONSchema(A,i.schema,o);else{const s=i.schema,n=A.processors[Q.type];if(!n)throw new Error(`[toJSONSchema]: Non-representable type encountered: ${Q.type}`);n(g,A,s,o)}const t=g._zod.parent;t&&(i.ref||(i.ref=t),HA(t,A,o),A.seen.get(t).isParent=!0)}const a=A.metadataRegistry.get(g);return a&&Object.assign(i.schema,a),A.io==="input"&&EB(g)&&(delete i.schema.examples,delete i.schema.default),A.io==="input"&&i.schema._prefault&&((I=i.schema).default??(I.default=i.schema._prefault)),delete i.schema._prefault,A.seen.get(g).schema}function $l(g,A){const B=g.seen.get(A);if(!B)throw new Error("Unprocessed schema. This is a bug in Zod.");const I=new Map;for(const i of g.seen.entries()){const e=g.metadataRegistry.get(i[0])?.id;if(e){const a=I.get(e);if(a&&a!==i[0])throw new Error(`Duplicate schema id "${e}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);I.set(e,i[0])}}const Q=i=>{const e=g.target==="draft-2020-12"?"$defs":"definitions";if(g.external){const t=g.external.registry.get(i[0])?.id,s=g.external.uri??(r=>r);if(t)return{ref:s(t)};const n=i[1].defId??i[1].schema.id??`schema${g.counter++}`;return i[1].defId=n,{defId:n,ref:`${s("__shared")}#/${e}/${n}`}}if(i[1]===B)return{ref:"#"};const C=`#/${e}/`,o=i[1].schema.id??`__schema${g.counter++}`;return{defId:o,ref:C+o}},E=i=>{if(i[1].schema.$ref)return;const e=i[1],{ref:a,defId:C}=Q(i);e.def={...e.schema},C&&(e.defId=C);const o=e.schema;for(const t in o)delete o[t];o.$ref=a};if(g.cycles==="throw")for(const i of g.seen.entries()){const e=i[1];if(e.cycle)throw new Error(`Cycle detected: #/${e.cycle?.join("/")}/<root>
|
|
48
48
|
|
|
49
|
-
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const i of g.seen.entries()){const e=i[1];if(A===i[0]){E(i);continue}if(g.external){const C=g.external.registry.get(i[0])?.id;if(A!==i[0]&&C){E(i);continue}}if(g.metadataRegistry.get(i[0])?.id){E(i);continue}if(e.cycle){E(i);continue}if(e.count>1&&g.reused==="ref"){E(i);continue}}}function AD(g,A){const B=g.seen.get(A);if(!B)throw new Error("Unprocessed schema. This is a bug in Zod.");const I=i=>{const e=g.seen.get(i);if(e.ref===null)return;const a=e.def??e.schema,C={...a},o=e.ref;if(e.ref=null,o){I(o);const s=g.seen.get(o),n=s.schema;if(n.$ref&&(g.target==="draft-07"||g.target==="draft-04"||g.target==="openapi-3.0")?(a.allOf=a.allOf??[],a.allOf.push(n)):Object.assign(a,n),Object.assign(a,C),i._zod.parent===o)for(const c in a)c==="$ref"||c==="allOf"||c in C||delete a[c];if(n.$ref&&s.def)for(const c in a)c==="$ref"||c==="allOf"||c in s.def&&JSON.stringify(a[c])===JSON.stringify(s.def[c])&&delete a[c]}const t=i._zod.parent;if(t&&t!==o){I(t);const s=g.seen.get(t);if(s?.schema.$ref&&(a.$ref=s.schema.$ref,s.def))for(const n in a)n==="$ref"||n==="allOf"||n in s.def&&JSON.stringify(a[n])===JSON.stringify(s.def[n])&&delete a[n]}g.override({zodSchema:i,jsonSchema:a,path:e.path??[]})};for(const i of[...g.seen.entries()].reverse())I(i[0]);const Q={};if(g.target==="draft-2020-12"?Q.$schema="https://json-schema.org/draft/2020-12/schema":g.target==="draft-07"?Q.$schema="http://json-schema.org/draft-07/schema#":g.target==="draft-04"?Q.$schema="http://json-schema.org/draft-04/schema#":g.target,g.external?.uri){const i=g.external.registry.get(A)?.id;if(!i)throw new Error("Schema is missing an `id` property");Q.$id=g.external.uri(i)}Object.assign(Q,B.def??B.schema);const E=g.external?.defs??{};for(const i of g.seen.entries()){const e=i[1];e.def&&e.defId&&(E[e.defId]=e.def)}g.external||Object.keys(E).length>0&&(g.target==="draft-2020-12"?Q.$defs=E:Q.definitions=E);try{const i=JSON.parse(JSON.stringify(Q));return Object.defineProperty(i,"~standard",{value:{...A["~standard"],jsonSchema:{input:pi(A,"input",g.processors),output:pi(A,"output",g.processors)}},enumerable:!1,writable:!1}),i}catch{throw new Error("Error converting schema to JSON.")}}function EB(g,A){const B=A??{seen:new Set};if(B.seen.has(g))return!1;B.seen.add(g);const I=g._zod.def;if(I.type==="transform")return!0;if(I.type==="array")return EB(I.element,B);if(I.type==="set")return EB(I.valueType,B);if(I.type==="lazy")return EB(I.getter(),B);if(I.type==="promise"||I.type==="optional"||I.type==="nonoptional"||I.type==="nullable"||I.type==="readonly"||I.type==="default"||I.type==="prefault")return EB(I.innerType,B);if(I.type==="intersection")return EB(I.left,B)||EB(I.right,B);if(I.type==="record"||I.type==="map")return EB(I.keyType,B)||EB(I.valueType,B);if(I.type==="pipe")return EB(I.in,B)||EB(I.out,B);if(I.type==="object"){for(const Q in I.shape)if(EB(I.shape[Q],B))return!0;return!1}if(I.type==="union"){for(const Q of I.options)if(EB(Q,B))return!0;return!1}if(I.type==="tuple"){for(const Q of I.items)if(EB(Q,B))return!0;return!!(I.rest&&EB(I.rest,B))}return!1}const tf=(g,A={})=>B=>{const I=_l({...B,processors:A});return HA(g,I),$l(I,g),AD(I,g)},pi=(g,A,B={})=>I=>{const{libraryOptions:Q,target:E}=I??{},i=_l({...Q??{},target:E,io:A,processors:B});return HA(g,i),$l(i,g),AD(i,g)},sf={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},nf=(g,A,B,I)=>{const Q=B;Q.type="string";const{minimum:E,maximum:i,format:e,patterns:a,contentEncoding:C}=g._zod.bag;if(typeof E=="number"&&(Q.minLength=E),typeof i=="number"&&(Q.maxLength=i),e&&(Q.format=sf[e]??e,Q.format===""&&delete Q.format,e==="time"&&delete Q.format),C&&(Q.contentEncoding=C),a&&a.size>0){const o=[...a];o.length===1?Q.pattern=o[0].source:o.length>1&&(Q.allOf=[...o.map(t=>({...A.target==="draft-07"||A.target==="draft-04"||A.target==="openapi-3.0"?{type:"string"}:{},pattern:t.source}))])}},rf=(g,A,B,I)=>{const Q=B,{minimum:E,maximum:i,format:e,multipleOf:a,exclusiveMaximum:C,exclusiveMinimum:o}=g._zod.bag;typeof e=="string"&&e.includes("int")?Q.type="integer":Q.type="number",typeof o=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(Q.minimum=o,Q.exclusiveMinimum=!0):Q.exclusiveMinimum=o),typeof E=="number"&&(Q.minimum=E,typeof o=="number"&&A.target!=="draft-04"&&(o>=E?delete Q.minimum:delete Q.exclusiveMinimum)),typeof C=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(Q.maximum=C,Q.exclusiveMaximum=!0):Q.exclusiveMaximum=C),typeof i=="number"&&(Q.maximum=i,typeof C=="number"&&A.target!=="draft-04"&&(C<=i?delete Q.maximum:delete Q.exclusiveMaximum)),typeof a=="number"&&(Q.multipleOf=a)},cf=(g,A,B,I)=>{B.type="boolean"},Gf=(g,A,B,I)=>{B.not={}},hf=(g,A,B,I)=>{},lf=(g,A,B,I)=>{const Q=g._zod.def,E=Gl(Q.entries);E.every(i=>typeof i=="number")&&(B.type="number"),E.every(i=>typeof i=="string")&&(B.type="string"),B.enum=E},Df=(g,A,B,I)=>{if(A.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},df=(g,A,B,I)=>{if(A.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},wf=(g,A,B,I)=>{const Q=B,E=g._zod.def,{minimum:i,maximum:e}=g._zod.bag;typeof i=="number"&&(Q.minItems=i),typeof e=="number"&&(Q.maxItems=e),Q.type="array",Q.items=HA(E.element,A,{...I,path:[...I.path,"items"]})},Ff=(g,A,B,I)=>{const Q=B,E=g._zod.def;Q.type="object",Q.properties={};const i=E.shape;for(const C in i)Q.properties[C]=HA(i[C],A,{...I,path:[...I.path,"properties",C]});const e=new Set(Object.keys(i)),a=new Set([...e].filter(C=>{const o=E.shape[C]._zod;return A.io==="input"?o.optin===void 0:o.optout===void 0}));a.size>0&&(Q.required=Array.from(a)),E.catchall?._zod.def.type==="never"?Q.additionalProperties=!1:E.catchall?E.catchall&&(Q.additionalProperties=HA(E.catchall,A,{...I,path:[...I.path,"additionalProperties"]})):A.io==="output"&&(Q.additionalProperties=!1)},Mf=(g,A,B,I)=>{const Q=g._zod.def,E=Q.inclusive===!1,i=Q.options.map((e,a)=>HA(e,A,{...I,path:[...I.path,E?"oneOf":"anyOf",a]}));E?B.oneOf=i:B.anyOf=i},Rf=(g,A,B,I)=>{const Q=g._zod.def,E=HA(Q.left,A,{...I,path:[...I.path,"allOf",0]}),i=HA(Q.right,A,{...I,path:[...I.path,"allOf",1]}),e=C=>"allOf"in C&&Object.keys(C).length===1,a=[...e(E)?E.allOf:[E],...e(i)?i.allOf:[i]];B.allOf=a},yf=(g,A,B,I)=>{const Q=B,E=g._zod.def;Q.type="object";const i=E.keyType,a=i._zod.bag?.patterns;if(E.mode==="loose"&&a&&a.size>0){const o=HA(E.valueType,A,{...I,path:[...I.path,"patternProperties","*"]});Q.patternProperties={};for(const t of a)Q.patternProperties[t.source]=o}else(A.target==="draft-07"||A.target==="draft-2020-12")&&(Q.propertyNames=HA(E.keyType,A,{...I,path:[...I.path,"propertyNames"]})),Q.additionalProperties=HA(E.valueType,A,{...I,path:[...I.path,"additionalProperties"]});const C=i._zod.values;if(C){const o=[...C].filter(t=>typeof t=="string"||typeof t=="number");o.length>0&&(Q.required=o)}},uf=(g,A,B,I)=>{const Q=g._zod.def,E=HA(Q.innerType,A,I),i=A.seen.get(g);A.target==="openapi-3.0"?(i.ref=Q.innerType,B.nullable=!0):B.anyOf=[E,{type:"null"}]},mf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType},Sf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType,B.default=JSON.parse(JSON.stringify(Q.defaultValue))},bf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType,A.io==="input"&&(B._prefault=JSON.parse(JSON.stringify(Q.defaultValue)))},pf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType;let i;try{i=Q.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}B.default=i},Yf=(g,A,B,I)=>{const Q=g._zod.def,E=A.io==="input"?Q.in._zod.def.type==="transform"?Q.out:Q.in:Q.out;HA(E,A,I);const i=A.seen.get(g);i.ref=E},Uf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType,B.readOnly=!0},BD=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType},ff=Z("ZodISODateTime",(g,A)=>{ZY.init(g,A),mA.init(g,A)});function kf(g){return xU(ff,g)}const Zf=Z("ZodISODate",(g,A)=>{NY.init(g,A),mA.init(g,A)});function Nf(g){return qU(Zf,g)}const Wf=Z("ZodISOTime",(g,A)=>{WY.init(g,A),mA.init(g,A)});function Hf(g){return LU(Wf,g)}const Jf=Z("ZodISODuration",(g,A)=>{HY.init(g,A),mA.init(g,A)});function xf(g){return VU(Jf,g)}const yB=Z("ZodError",(g,A)=>{Fl.init(g,A),g.name="ZodError",Object.defineProperties(g,{format:{value:B=>Sp(g,B)},flatten:{value:B=>mp(g,B)},addIssue:{value:B=>{g.issues.push(B),g.message=JSON.stringify(g.issues,NC,2)}},addIssues:{value:B=>{g.issues.push(...B),g.message=JSON.stringify(g.issues,NC,2)}},isEmpty:{get(){return g.issues.length===0}}})},{Parent:Error}),qf=qC(yB),Lf=LC(yB),Vf=Ri(yB),vf=yi(yB),Xf=Yp(yB),Kf=Up(yB),zf=fp(yB),Tf=kp(yB),Of=Zp(yB),jf=Np(yB),Pf=Wp(yB),_f=Hp(yB),YA=Z("ZodType",(g,A)=>(pA.init(g,A),Object.assign(g["~standard"],{jsonSchema:{input:pi(g,"input"),output:pi(g,"output")}}),g.toJSONSchema=tf(g,{}),g.def=A,g.type=A.type,Object.defineProperty(g,"_def",{value:A}),g.check=(...B)=>g.clone(Yg(A,{checks:[...A.checks??[],...B.map(I=>typeof I=="function"?{_zod:{check:I,def:{check:"custom"},onattach:[]}}:I)]}),{parent:!0}),g.with=g.check,g.clone=(B,I)=>Ug(g,B,I),g.brand=()=>g,g.register=((B,I)=>(B.add(g,I),g)),g.parse=(B,I)=>qf(g,B,I,{callee:g.parse}),g.safeParse=(B,I)=>Vf(g,B,I),g.parseAsync=async(B,I)=>Lf(g,B,I,{callee:g.parseAsync}),g.safeParseAsync=async(B,I)=>vf(g,B,I),g.spa=g.safeParseAsync,g.encode=(B,I)=>Xf(g,B,I),g.decode=(B,I)=>Kf(g,B,I),g.encodeAsync=async(B,I)=>zf(g,B,I),g.decodeAsync=async(B,I)=>Tf(g,B,I),g.safeEncode=(B,I)=>Of(g,B,I),g.safeDecode=(B,I)=>jf(g,B,I),g.safeEncodeAsync=async(B,I)=>Pf(g,B,I),g.safeDecodeAsync=async(B,I)=>_f(g,B,I),g.refine=(B,I)=>g.check(vk(B,I)),g.superRefine=B=>g.check(Xk(B)),g.overwrite=B=>g.check(NI(B)),g.optional=()=>aD(g),g.exactOptional=()=>Yk(g),g.nullable=()=>CD(g),g.nullish=()=>aD(CD(g)),g.nonoptional=B=>Wk(g,B),g.array=()=>zA(g),g.or=B=>TC([g,B]),g.and=B=>uk(g,B),g.transform=B=>tD(g,bk(B)),g.default=B=>kk(g,B),g.prefault=B=>Nk(g,B),g.catch=B=>Jk(g,B),g.pipe=B=>tD(g,B),g.readonly=()=>Lk(g),g.describe=B=>{const I=g.clone();return qQ.add(I,{description:B}),I},Object.defineProperty(g,"description",{get(){return qQ.get(g)?.description},configurable:!0}),g.meta=(...B)=>{if(B.length===0)return qQ.get(g);const I=g.clone();return qQ.add(I,B[0]),I},g.isOptional=()=>g.safeParse(void 0).success,g.isNullable=()=>g.safeParse(null).success,g.apply=B=>B(g),g)),gD=Z("_ZodString",(g,A)=>{VC.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(I,Q,E)=>nf(g,I,Q);const B=g._zod.bag;g.format=B.format??null,g.minLength=B.minimum??null,g.maxLength=B.maximum??null,g.regex=(...I)=>g.check(OU(...I)),g.includes=(...I)=>g.check(_U(...I)),g.startsWith=(...I)=>g.check($U(...I)),g.endsWith=(...I)=>g.check(Af(...I)),g.min=(...I)=>g.check(bi(...I)),g.max=(...I)=>g.check(jl(...I)),g.length=(...I)=>g.check(Pl(...I)),g.nonempty=(...I)=>g.check(bi(1,...I)),g.lowercase=I=>g.check(jU(I)),g.uppercase=I=>g.check(PU(I)),g.trim=()=>g.check(gf()),g.normalize=(...I)=>g.check(Bf(...I)),g.toLowerCase=()=>g.check(If()),g.toUpperCase=()=>g.check(Qf()),g.slugify=()=>g.check(Ef())}),$f=Z("ZodString",(g,A)=>{VC.init(g,A),gD.init(g,A),g.email=B=>g.check(DU(Ak,B)),g.url=B=>g.check(RU(Bk,B)),g.jwt=B=>g.check(JU(Gk,B)),g.emoji=B=>g.check(yU(gk,B)),g.guid=B=>g.check(Kl(ID,B)),g.uuid=B=>g.check(dU(Yi,B)),g.uuidv4=B=>g.check(wU(Yi,B)),g.uuidv6=B=>g.check(FU(Yi,B)),g.uuidv7=B=>g.check(MU(Yi,B)),g.nanoid=B=>g.check(uU(Ik,B)),g.guid=B=>g.check(Kl(ID,B)),g.cuid=B=>g.check(mU(Qk,B)),g.cuid2=B=>g.check(SU(Ek,B)),g.ulid=B=>g.check(bU(ik,B)),g.base64=B=>g.check(NU(nk,B)),g.base64url=B=>g.check(WU(rk,B)),g.xid=B=>g.check(pU(ek,B)),g.ksuid=B=>g.check(YU(ak,B)),g.ipv4=B=>g.check(UU(Ck,B)),g.ipv6=B=>g.check(fU(ok,B)),g.cidrv4=B=>g.check(kU(tk,B)),g.cidrv6=B=>g.check(ZU(sk,B)),g.e164=B=>g.check(HU(ck,B)),g.datetime=B=>g.check(kf(B)),g.date=B=>g.check(Nf(B)),g.time=B=>g.check(Hf(B)),g.duration=B=>g.check(xf(B))});function O(g){return lU($f,g)}const mA=Z("ZodStringFormat",(g,A)=>{yA.init(g,A),gD.init(g,A)}),Ak=Z("ZodEmail",(g,A)=>{uY.init(g,A),mA.init(g,A)}),ID=Z("ZodGUID",(g,A)=>{RY.init(g,A),mA.init(g,A)}),Yi=Z("ZodUUID",(g,A)=>{yY.init(g,A),mA.init(g,A)}),Bk=Z("ZodURL",(g,A)=>{mY.init(g,A),mA.init(g,A)}),gk=Z("ZodEmoji",(g,A)=>{SY.init(g,A),mA.init(g,A)}),Ik=Z("ZodNanoID",(g,A)=>{bY.init(g,A),mA.init(g,A)}),Qk=Z("ZodCUID",(g,A)=>{pY.init(g,A),mA.init(g,A)}),Ek=Z("ZodCUID2",(g,A)=>{YY.init(g,A),mA.init(g,A)}),ik=Z("ZodULID",(g,A)=>{UY.init(g,A),mA.init(g,A)}),ek=Z("ZodXID",(g,A)=>{fY.init(g,A),mA.init(g,A)}),ak=Z("ZodKSUID",(g,A)=>{kY.init(g,A),mA.init(g,A)}),Ck=Z("ZodIPv4",(g,A)=>{JY.init(g,A),mA.init(g,A)}),ok=Z("ZodIPv6",(g,A)=>{xY.init(g,A),mA.init(g,A)}),tk=Z("ZodCIDRv4",(g,A)=>{qY.init(g,A),mA.init(g,A)}),sk=Z("ZodCIDRv6",(g,A)=>{LY.init(g,A),mA.init(g,A)}),nk=Z("ZodBase64",(g,A)=>{VY.init(g,A),mA.init(g,A)}),rk=Z("ZodBase64URL",(g,A)=>{XY.init(g,A),mA.init(g,A)}),ck=Z("ZodE164",(g,A)=>{KY.init(g,A),mA.init(g,A)}),Gk=Z("ZodJWT",(g,A)=>{TY.init(g,A),mA.init(g,A)}),QD=Z("ZodNumber",(g,A)=>{fl.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(I,Q,E)=>rf(g,I,Q),g.gt=(I,Q)=>g.check(Tl(I,Q)),g.gte=(I,Q)=>g.check(KC(I,Q)),g.min=(I,Q)=>g.check(KC(I,Q)),g.lt=(I,Q)=>g.check(zl(I,Q)),g.lte=(I,Q)=>g.check(XC(I,Q)),g.max=(I,Q)=>g.check(XC(I,Q)),g.int=I=>g.check(ED(I)),g.safe=I=>g.check(ED(I)),g.positive=I=>g.check(Tl(0,I)),g.nonnegative=I=>g.check(KC(0,I)),g.negative=I=>g.check(zl(0,I)),g.nonpositive=I=>g.check(XC(0,I)),g.multipleOf=(I,Q)=>g.check(Ol(I,Q)),g.step=(I,Q)=>g.check(Ol(I,Q)),g.finite=()=>g;const B=g._zod.bag;g.minValue=Math.max(B.minimum??Number.NEGATIVE_INFINITY,B.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,g.maxValue=Math.min(B.maximum??Number.POSITIVE_INFINITY,B.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,g.isInt=(B.format??"").includes("int")||Number.isSafeInteger(B.multipleOf??.5),g.isFinite=!0,g.format=B.format??null});function K(g){return vU(QD,g)}const hk=Z("ZodNumberFormat",(g,A)=>{OY.init(g,A),QD.init(g,A)});function ED(g){return XU(hk,g)}const lk=Z("ZodBoolean",(g,A)=>{jY.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>cf(g,B,I)});function zC(g){return KU(lk,g)}const Dk=Z("ZodUnknown",(g,A)=>{PY.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>hf()});function iD(){return zU(Dk)}const dk=Z("ZodNever",(g,A)=>{_Y.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Gf(g,B,I)});function wk(g){return TU(dk,g)}const Fk=Z("ZodArray",(g,A)=>{$Y.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>wf(g,B,I,Q),g.element=A.element,g.min=(B,I)=>g.check(bi(B,I)),g.nonempty=B=>g.check(bi(1,B)),g.max=(B,I)=>g.check(jl(B,I)),g.length=(B,I)=>g.check(Pl(B,I)),g.unwrap=()=>g.element});function zA(g,A){return ef(Fk,g,A)}const Mk=Z("ZodObject",(g,A)=>{BU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Ff(g,B,I,Q),lA(g,"shape",()=>A.shape),g.keyof=()=>fi(Object.keys(g._zod.def.shape)),g.catchall=B=>g.clone({...g._zod.def,catchall:B}),g.passthrough=()=>g.clone({...g._zod.def,catchall:iD()}),g.loose=()=>g.clone({...g._zod.def,catchall:iD()}),g.strict=()=>g.clone({...g._zod.def,catchall:wk()}),g.strip=()=>g.clone({...g._zod.def,catchall:void 0}),g.extend=B=>Fp(g,B),g.safeExtend=B=>Mp(g,B),g.merge=B=>Rp(g,B),g.pick=B=>dp(g,B),g.omit=B=>wp(g,B),g.partial=(...B)=>yp(eD,g,B[0]),g.required=(...B)=>up(oD,g,B[0])});function wA(g,A){const B={type:"object",shape:g??{},...gA(A)};return new Mk(B)}const Rk=Z("ZodUnion",(g,A)=>{gU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Mf(g,B,I,Q),g.options=A.options});function TC(g,A){return new Rk({type:"union",options:g,...gA(A)})}const yk=Z("ZodIntersection",(g,A)=>{IU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Rf(g,B,I,Q)});function uk(g,A){return new yk({type:"intersection",left:g,right:A})}const mk=Z("ZodRecord",(g,A)=>{QU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>yf(g,B,I,Q),g.keyType=A.keyType,g.valueType=A.valueType});function Ui(g,A,B){return new mk({type:"record",keyType:g,valueType:A,...gA(B)})}const OC=Z("ZodEnum",(g,A)=>{EU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(I,Q,E)=>lf(g,I,Q),g.enum=A.entries,g.options=Object.values(A.entries);const B=new Set(Object.keys(A.entries));g.extract=(I,Q)=>{const E={};for(const i of I)if(B.has(i))E[i]=A.entries[i];else throw new Error(`Key ${i} not found in enum`);return new OC({...A,checks:[],...gA(Q),entries:E})},g.exclude=(I,Q)=>{const E={...A.entries};for(const i of I)if(B.has(i))delete E[i];else throw new Error(`Key ${i} not found in enum`);return new OC({...A,checks:[],...gA(Q),entries:E})}});function fi(g,A){const B=Array.isArray(g)?Object.fromEntries(g.map(I=>[I,I])):g;return new OC({type:"enum",entries:B,...gA(A)})}const Sk=Z("ZodTransform",(g,A)=>{iU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>df(g,B),g._zod.parse=(B,I)=>{if(I.direction==="backward")throw new rl(g.constructor.name);B.addIssue=E=>{if(typeof E=="string")B.issues.push(xQ(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=g),B.issues.push(xQ(i))}};const Q=A.transform(B.value,B);return Q instanceof Promise?Q.then(E=>(B.value=E,B)):(B.value=Q,B)}});function bk(g){return new Sk({type:"transform",transform:g})}const eD=Z("ZodOptional",(g,A)=>{xl.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>BD(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function aD(g){return new eD({type:"optional",innerType:g})}const pk=Z("ZodExactOptional",(g,A)=>{eU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>BD(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Yk(g){return new pk({type:"optional",innerType:g})}const Uk=Z("ZodNullable",(g,A)=>{aU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>uf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function CD(g){return new Uk({type:"nullable",innerType:g})}const fk=Z("ZodDefault",(g,A)=>{CU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Sf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType,g.removeDefault=g.unwrap});function kk(g,A){return new fk({type:"default",innerType:g,get defaultValue(){return typeof A=="function"?A():dl(A)}})}const Zk=Z("ZodPrefault",(g,A)=>{oU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>bf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Nk(g,A){return new Zk({type:"prefault",innerType:g,get defaultValue(){return typeof A=="function"?A():dl(A)}})}const oD=Z("ZodNonOptional",(g,A)=>{tU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>mf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Wk(g,A){return new oD({type:"nonoptional",innerType:g,...gA(A)})}const Hk=Z("ZodCatch",(g,A)=>{sU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>pf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType,g.removeCatch=g.unwrap});function Jk(g,A){return new Hk({type:"catch",innerType:g,catchValue:typeof A=="function"?A:()=>A})}const xk=Z("ZodPipe",(g,A)=>{nU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Yf(g,B,I,Q),g.in=A.in,g.out=A.out});function tD(g,A){return new xk({type:"pipe",in:g,out:A})}const qk=Z("ZodReadonly",(g,A)=>{rU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Uf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Lk(g){return new qk({type:"readonly",innerType:g})}const Vk=Z("ZodCustom",(g,A)=>{cU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Df(g,B)});function vk(g,A={}){return af(Vk,g,A)}function Xk(g){return Cf(g)}const Kk=Sg.map(g=>g),sD=wA({id:O(),uuid:O(),playlist_index:K().nonnegative(),chain_name:O(),token_address:O().optional(),token_id:O().optional(),tx_id:O().optional(),platform:O(),title:O(),artist:O(),description:O().optional(),album:O().optional(),image_url:O().url(),image_thumb_url:O().url().optional(),audio_url:O().url(),audio_url_lossless:O().url().optional(),duration:K().nonnegative(),genre:O(),tags:zA(O()),bpm:K().positive().optional(),key:O().optional(),attributes:Ui(O(),TC([O(),K()])).optional()}).refine(g=>g.chain_name==="AR"?!!g.tx_id:!!g.token_address&&!!g.token_id,{message:"AR chain tracks must have tx_id; other chains must have token_address and token_id",path:["chain_name"]}),zk=wA({name:O(),description:O().optional(),image:O().url(),creator:O(),genre:O().optional(),tags:zA(O()).optional(),tracks:zA(sD)}),Tk=wA({bass_dominance:K().min(0).max(1),mid_dominance:K().min(0).max(1),treble_dominance:K().min(0).max(1),average_amplitude:K().min(0).max(1),spectral_centroid:K().optional(),spectral_rolloff:K().optional(),zero_crossing_rate:K().optional(),color_palette:wA({colors:zA(O()),primary_color:O(),secondary_color:O().optional(),accent_color:O().optional(),brightness:K().min(0).max(1),saturation:K().min(0).max(1),is_monochrome:zC()}).optional(),analysis_metadata:wA({duration_analyzed:K().positive(),full_buffer_analyzed:zC(),sample_positions:zA(K()),analyzed_at:O()})}),jC=wA({STR:K().min(1).max(20),DEX:K().min(1).max(20),CON:K().min(1).max(20),INT:K().min(1).max(20),WIS:K().min(1).max(20),CHA:K().min(1).max(20)}),Ok=wA({name:O(),race:fi(["Human","Elf","Dwarf","Halfling","Dragonborn","Gnome","Half-Elf","Half-Orc","Tiefling"]),class:fi(Kk),level:K().min(1).max(20),ability_scores:jC,ability_modifiers:jC,proficiency_bonus:K().min(2).max(6),hp:wA({current:K().nonnegative(),max:K().positive(),temp:K().nonnegative()}),armor_class:K().positive(),initiative:K(),speed:K().positive(),skills:Ui(O(),fi(["none","proficient","expertise"])),saving_throws:Ui(O(),zC()),racial_traits:zA(O()),class_features:zA(O()),spells:wA({spell_slots:Ui(O(),wA({total:K().nonnegative(),used:K().nonnegative()})),known_spells:zA(O()),cantrips:zA(O())}).optional(),equipment:wA({weapons:zA(O()),armor:zA(O()),items:zA(O())}).optional(),appearance:wA({body_type:O(),skin_tone:O(),hair_style:O(),hair_color:O(),eye_color:O(),facial_features:zA(O()),primary_color:O().optional(),secondary_color:O().optional(),aura_color:O().optional()}).optional(),xp:wA({current:K().nonnegative(),next_level:K().positive()}),seed:O(),generated_at:O()});var nD=(g=>(g[g.DEBUG=0]="DEBUG",g[g.INFO=1]="INFO",g[g.WARN=2]="WARN",g[g.ERROR=3]="ERROR",g[g.NONE=4]="NONE",g))(nD||{});const jk={0:"DEBUG",1:"INFO",2:"WARN",3:"ERROR",4:"NONE"};let PB=1,PC=!0,_C=!0,ki=null,Zi=!1,LQ=!1;class VA{constructor(A){this.context=A}static for(A){return new VA(A)}static enableDiagnosticMode(){Zi=!0,PB=0}static disableDiagnosticMode(){Zi=!1,PB=1}static isDiagnosticMode(){return Zi}static enableVerbose(){LQ=!0,PB=0}static disableVerbose(){LQ=!1,PB=1}static isVerbose(){return LQ}static setVerbose(A){LQ=A,PB=A?0:1}static setLevel(A){PB=A}static getLevel(){return PB}static configure(A){A.level!==void 0&&(PB=A.level),A.includeTimestamp!==void 0&&(PC=A.includeTimestamp),A.includeContext!==void 0&&(_C=A.includeContext),A.customHandler!==void 0&&(ki=A.customHandler)}static reset(){PB=1,PC=!0,_C=!0,ki=null,Zi=!1,LQ=!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,I){if(A<PB)return;const Q={timestamp:new Date,level:A,context:this.context,message:B,data:I};if(ki){ki(Q);return}const E=this.formatMessage(Q);switch(A){case 0:I!==void 0?console.debug(E,I):console.debug(E);break;case 1:I!==void 0?console.info(E,I):console.info(E);break;case 2:I!==void 0?console.warn(E,I):console.warn(E);break;case 3:I!==void 0?console.error(E,I):console.error(E);break}}formatMessage(A){const B=[];return PC&&B.push(this.formatTimestamp(A.timestamp)),B.push(`[${jk[A.level]}]`),_C&&A.context&&B.push(`[${A.context}]`),B.push(A.message),B.join(" ")}formatTimestamp(A){const B=A.getHours().toString().padStart(2,"0"),I=A.getMinutes().toString().padStart(2,"0"),Q=A.getSeconds().toString().padStart(2,"0"),E=A.getMilliseconds().toString().padStart(3,"0");return`${B}:${I}:${Q}.${E}`}}function Pk(g){return VA.for(g)}class eA{static extractAudioUrl(A){const B=["mp3_url","lossy_audio","animation_url","audio_url","lossless_audio","audio","multimedia_url","losslessAudio"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];return null}static extractAudioUrlLossless(A){const B=["lossless_audio","wav_url","flac_url","losslessAudio","audio_url"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];return null}static extractImageUrl(A){const B=["image_small","image","image_large","image_thumb","image_url","image_uri","image_preview"];for(const Q of B)if(A[Q]&&typeof A[Q]=="string")return A[Q];const I=[this.extractNestedUri(A,"artwork","uri"),this.extractNestedUri(A,"project","artwork","uri"),this.extractNestedUri(A,"primaryMedia","uri")];for(const Q of I)if(Q)return Q;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 I of B)if(A[I]&&typeof A[I]=="string")return A[I];if(Array.isArray(A.attributes)){const I=A.attributes.find(Q=>Q.trait_type?.toLowerCase()==="artist"&&Q.value!==void 0);if(I&&typeof I.value=="string")return I.value}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(I=>I.trait_type?.toLowerCase()==="genre"&&I.value!==void 0);if(B){if(typeof B.value=="string")return B.value;if(Array.isArray(B.value)&&B.value.length>0){const I=B.value[0];return typeof I=="string"?I:""}}}return""}static convertAttributes(A){if(!Array.isArray(A))return null;const B={};for(const I of A)I.trait_type&&I.value!==void 0&&(B[I.trait_type]=I.value);return Object.keys(B).length>0?B:null}static extractNestedUri(A,...B){let I=A;for(const Q of B)if(I&&typeof I=="object"&&!Array.isArray(I))I=I[Q];else return null;return typeof I=="string"?I:null}}function $C(g){if("audio_url"in g&&typeof g.audio_url=="string")return g.audio_url;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A)return eA.extractAudioUrl(A)}return null}function _k(g){if("audio_url_lossless"in g&&typeof g.audio_url_lossless=="string")return g.audio_url_lossless;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A)return eA.extractAudioUrlLossless(A)}return null}function Ao(g){if("image_url"in g&&typeof g.image_url=="string")return g.image_url;if("metadata"in g){if("artwork_url"in g&&typeof g.artwork_url=="string")return g.artwork_url;const A=eA.parseMetadata(g.metadata);if(A)return eA.extractImageUrl(A)}return null}function rD(g){if("image_thumb_url"in g&&typeof g.image_thumb_url=="string")return g.image_thumb_url;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A)return eA.extractImageThumbUrl(A)}return null}function cD(g){if("audio_url"in g)return null;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A&&typeof A.vrm=="string"&&A.vrm)return A.vrm}return null}function $k(g){const A=[];for(const B of g.tracks){const I=$C(B);I&&A.push(I)}return A}function AZ(g){const A=[];for(const B of g.tracks){const I=Ao(B);I&&A.push(I)}return A}function BZ(g){const A=[];for(const B of g.tracks){if("title"in B&&typeof B.title=="string"){A.push(B.title);continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I){const Q=eA.extractTitle(I);Q&&A.push(Q)}}}return A}function gZ(g){const A=[];for(const B of g.tracks){if("artist"in B&&typeof B.artist=="string"){A.push(B.artist);continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I){const Q=eA.extractArtist(I);Q&&A.push(Q)}}}return A}function IZ(g){const A=new Set;for(const B of g.tracks){if("genre"in B&&typeof B.genre=="string"&&B.genre){A.add(B.genre);continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);I&&typeof I.genre=="string"&&I.genre&&A.add(I.genre)}}return Array.from(A).sort()}function QZ(g){const A=new Set;for(const B of g.tracks){if("tags"in B&&Array.isArray(B.tags)){for(const I of B.tags)I&&A.add(I.toLowerCase());continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I&&Array.isArray(I.tags))for(const Q of I.tags)Q&&A.add(String(Q).toLowerCase())}}return Array.from(A).sort()}function EZ(g){let A=0;for(const B of g.tracks){if("duration"in B&&typeof B.duration=="number"){A+=B.duration;continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);I&&typeof I.duration=="number"&&(A+=I.duration)}}return A}function iZ(g){return g.tracks.length}function eZ(g){const A=[];for(const B of g.tracks){const I=$C(B),Q=Ao(B),E=rD(B);let i="",e="";if("title"in B)i=B.title||"",e=B.artist||"";else if("metadata"in B){const a=eA.parseMetadata(B.metadata);a&&(i=eA.extractTitle(a)||"",e=eA.extractArtist(a)||"")}if(I){const a={title:i,artist:e,audio_url:I,image_url:Q||""},C=_k(B);C&&C!==I&&(a.audio_url_lossless=C),E&&(a.image_thumb_url=E),"audio_ipfs_hash"in B&&typeof B.audio_ipfs_hash=="string"&&(a.audio_ipfs_hash=B.audio_ipfs_hash),"artwork_ipfs_hash"in B&&typeof B.artwork_ipfs_hash=="string"&&(a.artwork_ipfs_hash=B.artwork_ipfs_hash),A.push(a)}}return A}function aZ(g){const A=[];for(const B of g.tracks){if("audio_url"in B){A.push({...B});continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I){const Q=eA.extractAudioUrlLossless(I),E=eA.extractAudioUrl(I);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:eA.extractTitle(I),artist:eA.extractArtist(I),audio_url:E,image_url:eA.extractImageUrl(I),image_thumb_url:eA.extractImageThumbUrl(I),duration:I.duration,genre:I.genre,tags:I.tags,bpm:I.bpm,key:I.key,album:I.album,description:I.description,attributes:eA.convertAttributes(I.attributes),...Q&&Q!==E?{audio_url_lossless:Q}:{},...B.audio_ipfs_hash?{audio_ipfs_hash:B.audio_ipfs_hash}:{},...B.artwork_ipfs_hash?{artwork_ipfs_hash:B.artwork_ipfs_hash}:{}})}}}return A}function CZ(g){const A=[];for(const B of g.tracks){const I=cD(B);I&&A.push(I)}return A}function oZ(g){const A=[];for(const B of g.tracks){const I=cD(B);if(!I)continue;const Q=$C(B),E=Ao(B),i=rD(B);let e="",a="";if("title"in B)e=B.title||"",a=B.artist||"";else if("metadata"in B){const o=eA.parseMetadata(B.metadata);o&&(e=eA.extractTitle(o)||"",a=eA.extractArtist(o)||"")}const C={title:e,artist:a,audio_url:Q||"",image_url:E||"",vrm:I};i&&(C.image_thumb_url=i),A.push(C)}return A}const Bo=[{host:"arweave.net",protocol:"https",priority:3},{host:"ardrive.net",protocol:"https",priority:2},{host:"turbo-gateway.com",protocol:"https",priority:1}],go=["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 WI(g){if(!g||typeof g!="string")return!1;if(g.startsWith("ar://"))return!0;const A=g.toLowerCase();try{const B=new URL(g).hostname;return go.some(I=>B===I||B.endsWith("."+I))}catch{return go.some(B=>A.includes(B))}}function HI(g){if(!g||typeof g!="string"||!WI(g))return null;let A=null,B="";if(g.startsWith("ar://")){const i=g.slice(5),e=i.indexOf("/");return e!==-1?(A=i.slice(0,e),B=i.slice(e)):A=i,A.length===43&&/^[A-Za-z0-9_-]+$/.test(A)?{txId:A,originalUrl:g,pathSuffix:B}:null}let I=g;try{const i=new URL(g);I=i.pathname+i.search}catch{}const Q=/[A-Za-z0-9_-]{43}/g,E=I.match(Q);if(E&&E.length>0){A=E[0];const i=g.indexOf(A);if(i!==-1){const e=g.slice(i+43),a=Math.min(e.indexOf("?")===-1?1/0:e.indexOf("?"),e.indexOf("#")===-1?1/0:e.indexOf("#"));a===1/0?B=e:B=e.slice(0,a)}return{txId:A,originalUrl:g,pathSuffix:B}}return null}function VB(g,A,B=""){return`${A.protocol||"https"}://${A.host}/${g}${B}`}function tZ(g,A=Bo,B=""){return A.sort((I,Q)=>I.priority-Q.priority).map(I=>VB(g,I,B))}async function sZ(){try{return await import("@ar.io/wayfinder-core")}catch{return null}}async function nZ(){try{return await import("@ar.io/sdk")}catch{return null}}const rZ="https://solana-rpc.publicnode.com",cZ=5e3,GZ=864e5,Io="arweave_active_gateway",Qo="arweave_ranked_gateways";class GD{constructor(A){this.cache=new Map,this.logger=VA.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.wayfinderGatewaysProvider=null,this.rankedGatewaysCache=null,this.rankedGatewaysCacheTimestamp=0,this.RANKED_GATEWAYS_TTL_MS=7200*1e3,this.activeGateway=null,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.gateways=(A?.gateways??Bo).map(I=>({...I})),this.timeout=A?.timeout??cZ,this.cacheTTL=A?.cacheTTL??GZ,this.slowResponseThreshold=A?.slowResponseThreshold??8e3,this.maxSlowResponses=A?.maxSlowResponses??3,this.solanaRpcUrl=A?.solanaRpcUrl??rZ,this.hasCustomSolanaRpc=typeof A?.solanaRpcUrl=="string"&&A.solanaRpcUrl.length>0,this.wayfinderSortBy=A?.wayfinderSortBy??"weights.compositeWeight",this.wayfinderPrimaryLimit=A?.wayfinderPrimaryLimit??50,this.wayfinderFallbackLimit=A?.wayfinderFallbackLimit??100,this.wayfinderStrategy=A?.wayfinderStrategy??"composite-ping-random",this.gateways.sort((I,Q)=>I.priority-Q.priority),this.gateways.forEach(I=>{this.originalPriorities.set(I.host,I.priority)}),this.activeGateway=this.loadPersistedGateway();const B=this.loadPersistedRankedGateways();B&&(this.rankedGatewaysCache=B),Promise.all([sZ(),nZ(),Promise.resolve().then(()=>HK)]).then(([I,Q,E])=>{if(I&&Q)try{const{FastestPingRoutingStrategy:i,RandomRoutingStrategy:e,CompositeRoutingStrategy:a,RoundRobinRoutingStrategy:C,NetworkGatewaysProvider:o}=I,t=Q.ARIO,s=E.createSolanaRpc(this.solanaRpcUrl),n=t.init({rpc:s}),r=new o({ario:n,sortBy:this.wayfinderSortBy,limit:this.wayfinderPrimaryLimit}),c=new o({ario:n,sortBy:this.wayfinderSortBy,limit:this.wayfinderFallbackLimit});this.wayfinderGatewaysProvider=r;const G=(()=>{switch(this.wayfinderStrategy){case"random-only":return new e({gatewaysProvider:c});case"ping-only":return new i({timeoutMs:3e3,gatewaysProvider:r});case"round-robin":return new C({gateways:[],gatewaysProvider:r});default:return new a({strategies:[new i({timeoutMs:3e3,gatewaysProvider:r}),new e({gatewaysProvider:c})]})}})();this.wayfinder=I.createWayfinderClient({routingStrategy:G}),this.logger.info("Wayfinder client initialized",{strategy:this.wayfinderStrategy,sortBy:this.wayfinderSortBy,primaryLimit:this.wayfinderPrimaryLimit,fallbackLimit:this.wayfinderFallbackLimit})}catch(i){this.logger.warn("Failed to configure Wayfinder routing strategy, using defaults",{error:i}),this.wayfinder=I.createWayfinderClient(),this.logger.info("Wayfinder client initialized with default routing")}else I&&(this.wayfinder=I.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(I=>I.host),timeout:this.timeout,cacheTTL:this.cacheTTL,activeGateway:this.activeGateway?.host??null})}withTimeout(A,B,I){return new Promise((Q,E)=>{const i=setTimeout(()=>E(new Error(I)),B);A.then(e=>{clearTimeout(i),Q(e)},e=>{clearTimeout(i),E(e)})})}resolveUrlSimple(A){if(!WI(A))return A;const B=HI(A);if(!B)return A;const I=this.activeGateway??this.gateways[0];return this.logger.debug("[gateway] resolveUrlSimple",{txId:B.txId,gateway:I.host,pathSuffix:B.pathSuffix||void 0}),VB(B.txId,I,B.pathSuffix)}setPreferredGateway(A){const B=this.gateways.find(I=>I.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(I=>I.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 I=this.healthData.get(B.host)??[],Q=I.length,E=Q>0?Math.round(I.reduce((e,a)=>e+a.responseTime,0)/Q):0,i=Q>0?I.filter(e=>e.success).length/Q:1;return{host:B.host,avgMs:E,successRate:Math.round(i*100)/100,checks:Q}});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 I=B?.signal;if(I?.aborted)return this.logger.debug("resolveUrl called with already-aborted signal, returning original URL"),A;if(!WI(A))return A;const Q=HI(A);if(!Q)return this.logger.warn("Failed to parse Arweave URL, returning original",{url:A}),A;const{txId:E,pathSuffix:i}=Q,e=this.getCachedGateway(E);if(e){this.hitCount++;const s=VB(E,e,i);return this.logger.debug("Cache hit for txId",{txId:E,gateway:e.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 C=this.inflightResolves.get(E);if(C)return this.logger.debug("Reusing in-flight resolve for txId",{txId:E}),C;const o=new AbortController;I&&I.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,I,Q,E){const i=Date.now(),e=E?.bypassArweaveNet??!1;let a=null;if(A.startsWith("https://")||A.startsWith("http://"))try{const r=new URL(A),c={host:r.host,protocol:r.protocol.replace(":",""),priority:0},G=Date.now(),D=await this.checkAndSetGateway(A,B,I,c,Q),h=Date.now()-G;if(D)return this.logger.info("[gateway] Step 0 (original): success",{host:c.host,ms:h,totalMs:Date.now()-i}),D;this.logger.info("[gateway] Step 0 (original): failed",{host:c.host,ms:h}),a=c.host}catch{}if(this.activeGateway&&this.activeGateway.host!==a){const r=Date.now(),c=await this.checkAndSetGateway(A,B,I,this.activeGateway,Q),G=Date.now()-r;if(c)return this.logger.info("[gateway] Step 1 (persisted): success",{host:this.activeGateway.host,ms:G,totalMs:Date.now()-i}),c;this.logger.info("[gateway] Step 1 (persisted): failed, clearing",{ms:G}),this.activeGateway=null,this.clearPersistedGateway()}if(!e&&a!=="arweave.net"){const r=this.gateways.find(c=>c.host==="arweave.net");if(r){const c=Date.now(),G=await this.checkAndSetGateway(A,B,I,r,Q),D=Date.now()-c;if(G)return this.logger.info("[gateway] Step 2 (arweave.net): success",{ms:D,totalMs:Date.now()-i}),G;this.logger.info("[gateway] Step 2 (arweave.net): failed",{ms:D})}}const C=Date.now(),o=await this.tryFallbackGateways(A,B,I,Q,a),t=Date.now()-C;if(o)return this.logger.info("[gateway] Step 3 (fallbacks): success",{ms:t,totalMs:Date.now()-i}),o;this.logger.info("[gateway] Step 3 (fallbacks): failed",{ms:t});const s=!this.hasCustomSolanaRpc,n=E?.bypassWayfinder??s;if(this.wayfinder&&!n){const r=Date.now();this.logger.info("[gateway] Step 4 (wayfinder): trying");const c=await this.tryWayfinder(B,I,Q,a),G=Date.now()-r;if(c)return this.logger.info("[gateway] Step 4 (wayfinder): success",{ms:G,totalMs:Date.now()-i}),c;this.logger.info("[gateway] Step 4 (wayfinder): failed",{ms:G})}return this.logger.warn("All gateways (arweave.net + Wayfinder + fallbacks) failed, returning original URL",{txId:B,pathSuffix:I,originalUrl:A}),A}async reportGatewayFailure(A,B){const{signal:I,reason:Q,excludeHost:E}=B??{};if(I?.aborted)return this.logger.debug("reportGatewayFailure called with already-aborted signal, returning original URL"),A;if(Q==="user-cancel-fast")return this.logger.debug("User cancelled quickly, keeping current gateway"),A;const i=HI(A);if(!i)return A;const{txId:e,pathSuffix:a}=i;this.logger.warn("Gateway failure reported, finding new gateway",{failedHost:this.activeGateway?.host,txId:e,reason:Q??"load-error"});const C=this.activeGateway?.host??E;this.activeGateway=null,this.cache.delete(e),this.clearPersistedGateway();const o=this.gateways.find(n=>n.host==="arweave.net"&&n.host!==C);if(o){const n=await this.checkAndSetGateway(A,e,a,o,I);if(n)return n}if(this.wayfinder){const n=await this.tryWayfinder(e,a,I);if(n)return n}const t=this.gateways;C&&(this.gateways=this.gateways.filter(n=>n.host!==C));const s=await this.tryFallbackGateways(A,e,a,I);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,I,Q,E){if(E?.aborted)return null;const i=await this.checkGateway(B,Q,I,E);if(i===!0){this.setActiveGateway(Q,B);const e=VB(B,Q,I);return this.logger.info("Gateway resolved",{txId:B,gateway:Q.host,pathSuffix:I,workingUrl:e}),e}if(i==="maybe"){const e=VB(B,Q,I);return this.logger.info("Gateway maybe resolved (no-cors)",{txId:B,gateway:Q.host,pathSuffix:I,workingUrl:e}),e}return null}async tryFallbackGateways(A,B,I,Q,E){this.missCount++;const i=.7,e=3,a=this.gateways.filter(n=>n.host!=="arweave.net"&&n.host!==E),C=a.filter(n=>{const{rate:r,totalChecks:c}=this.getFailureRate(n.host);return!(c>=e&&r>i)}),o=C.length>0?C:a;if(Q?.aborted||o.length===0)return null;const t=async n=>{if(Q?.aborted||n.length===0)return null;const r=new AbortController,c=()=>r.abort();Q?.addEventListener("abort",c,{once:!0});let G=!1;try{return await Promise.any(n.map(async h=>{const w=await this.checkGateway(B,h,I,r.signal);if(w){const y=VB(B,h,I);return G||(G=!0,w===!0?(this.setActiveGateway(h,B),this.logger.info("Gateway resolved via fallback",{txId:B,gateway:h.host,pathSuffix:I,workingUrl:y})):this.logger.info("Gateway maybe resolved via fallback (no-cors)",{txId:B,gateway:h.host,pathSuffix:I,workingUrl:y})),y}throw new Error(`Gateway ${h.host} failed check`)}))}catch{return null}finally{Q?.removeEventListener("abort",c)}},s=await t(o);if(s)return s;if(C.length<a.length&&!Q?.aborted){const n=a.filter(c=>!C.some(G=>G.host===c.host)).map(c=>c.host);this.logger.debug("Healthy gateways exhausted, retrying with previously unhealthy",{excludedHosts:n});const r=await t(a);if(r)return r}return null}async getRankedGatewaysCached(A){if(!this.wayfinderGatewaysProvider)return null;const B=Date.now(),I=B-this.rankedGatewaysCacheTimestamp;if(this.rankedGatewaysCache&&I<this.RANKED_GATEWAYS_TTL_MS)return this.logger.debug("Reusing cached ranked gateway list",{size:this.rankedGatewaysCache.length,ageMs:I}),this.rankedGatewaysCache;try{const Q=await this.withTimeout(this.wayfinderGatewaysProvider.getGateways(),this.timeout+2e3,"Wayfinder provider getGateways timed out");return A?.aborted?null:(this.rankedGatewaysCache=Q,this.rankedGatewaysCacheTimestamp=B,this.persistRankedGateways(Q,B),this.logger.info("Refreshed ranked gateway list cache",{size:Q.length}),Q)}catch(Q){return this.logger.debug("Failed to fetch ranked gateway list from provider",{error:Q}),this.rankedGatewaysCache?(this.logger.debug("Falling back to stale ranked gateway cache",{size:this.rankedGatewaysCache.length,ageMs:I}),this.rankedGatewaysCache):null}}async tryWayfinder(A,B,I,Q){if(!this.wayfinder)return null;const E=10,i=new Set;Q&&i.add(Q);const e=`https://arweave.net/${A}${B}`;try{this.logger.debug("Resolving via Wayfinder (first pick)",{txId:A,normalizedUrl:e});const o=await this.withTimeout(this.wayfinder.resolveUrl({originalUrl:e}),this.timeout+2e3,"Wayfinder resolution timed out");if(I?.aborted)return null;const t=o.hostname;if(i.has(t))this.logger.debug("Wayfinder first pick was already excluded, skipping to walk",{host:t});else{const s=o.protocol.replace(":",""),n={host:t,protocol:s,priority:0},r=await this.checkGateway(A,n,B,I);if(r){const c=VB(A,n,B);return r===!0?(this.setActiveGateway(n,A),this.logger.info("Gateway resolved via Wayfinder (first pick)",{txId:A,gateway:t,pathSuffix:B,workingUrl:c})):this.logger.info("Gateway maybe resolved via Wayfinder (first pick, no-cors)",{txId:A,gateway:t,pathSuffix:B,workingUrl:c}),c}this.logger.debug("Wayfinder first pick failed verify, will walk ranked list",{host:t}),i.add(t)}}catch(o){this.logger.debug("Wayfinder first pick threw, will walk ranked list",{error:o})}if(I?.aborted)return null;const a=await this.getRankedGatewaysCached(I);if(!a||a.length===0||I?.aborted)return null;const C=a.filter(o=>!i.has(o.hostname)).slice(0,E);this.logger.debug("Walking Wayfinder ranked list",{txId:A,poolSize:a.length,walkSize:C.length});for(const o of C){if(I?.aborted)return null;const t={host:o.hostname,protocol:o.protocol.replace(":",""),priority:0},s=await this.checkGateway(A,t,B,I);if(s){const n=VB(A,t,B);return s===!0?(this.setActiveGateway(t,A),this.logger.info("Gateway resolved via Wayfinder ranked walk",{txId:A,gateway:t.host,pathSuffix:B,workingUrl:n})):this.logger.info("Gateway maybe resolved via Wayfinder ranked walk (no-cors)",{txId:A,gateway:t.host,pathSuffix:B,workingUrl:n}),n}i.add(t.host)}return this.logger.debug("Wayfinder ranked walk exhausted with no match",{txId:A,checkedHosts:Array.from(i)}),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(Io);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:Q,...E}=B;return E}}catch{}return null}loadPersistedRankedGateways(){try{if(typeof localStorage>"u")return null;const A=localStorage.getItem(Qo);if(!A)return null;const B=JSON.parse(A);if(!B||!Array.isArray(B.gateways)||typeof B.timestamp!="number")return null;const I=Date.now()-B.timestamp;if(I>this.RANKED_GATEWAYS_TTL_MS)return this.logger.info("Ignoring persisted ranked gateway list — expired",{ageMs:I}),this.clearPersistedRankedGateways(),null;const Q=[];for(const E of B.gateways)if(typeof E=="string")try{Q.push(new URL(E))}catch{}return Q.length===0?null:(this.rankedGatewaysCacheTimestamp=B.timestamp,this.logger.info("Restored ranked gateway list from localStorage",{size:Q.length,ageMs:I}),Q)}catch{return null}}persistRankedGateways(A,B){try{if(typeof localStorage>"u")return;const I={gateways:A.map(Q=>Q.toString()),timestamp:B};localStorage.setItem(Qo,JSON.stringify(I))}catch{}}clearPersistedRankedGateways(){try{if(typeof localStorage>"u")return;localStorage.removeItem(Qo)}catch{}}persistGateway(A){try{if(typeof localStorage>"u")return;const B={...A,timestamp:Date.now()};localStorage.setItem(Io,JSON.stringify(B))}catch{}}clearPersistedGateway(){try{if(typeof localStorage>"u")return;localStorage.removeItem(Io)}catch{}}async checkGateway(A,B,I="",Q){const E=VB(A,B,I),i=Date.now(),e=new AbortController,a=setTimeout(()=>e.abort(),this.timeout),C=()=>e.abort();Q?.addEventListener("abort",C,{once:!0});try{const o=await fetch(E,{method:"HEAD",mode:"cors",signal:e.signal});clearTimeout(a),Q?.removeEventListener("abort",C);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),Q?.removeEventListener("abort",C);const t=Date.now()-i;if(this.recordGatewayResponse(B.host,t,!1),o instanceof Error&&o.name==="AbortError"){const s=Q?.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:e.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 I={txId:A,workingGateway:B,timestamp:Date.now(),ttl:this.cacheTTL};this.cache.set(A,I),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(!WI(A))return;const B=HI(A);B&&(this.cache.delete(B.txId),this.activeGateway=null,this.clearPersistedGateway())}async prefetchUrls(A,B){const I=B?.concurrency??5,Q=B?.continueOnError??!0,E=[];let i=0,e=0,a=0;for(let C=0;C<A.length;C+=I){const o=A.slice(C,C+I),t=await Promise.allSettled(o.map(async s=>{if(!WI(s))return{url:s,txId:"",success:!1,error:"Not an Arweave URL"};const n=HI(s);if(!n)return{url:s,txId:"",success:!1,error:"Failed to parse Arweave URL"};const r=this.getCachedGateway(n.txId);if(r)return{url:s,txId:n.txId,success:!0,gateway:r};await this.resolveUrl(s);const c=this.getCachedGateway(n.txId);return c?{url:s,txId:n.txId,success:!0,gateway:c}:{url:s,txId:n.txId,success:!1,error:"All gateways failed"}}));for(const s of t)if(s.status==="fulfilled"){const n=s.value;E.push(n),n.error==="Not an Arweave URL"?a++:n.success?i++:e++}else e++,E.push({url:"unknown",txId:"",success:!1,error:s.reason?.message??"Unknown error"});if(!Q&&e>0){this.logger.warn("Prefetch stopped due to failures",{failed:e,processed:E.length});break}}return this.logger.info("Prefetch complete",{total:A.length,succeeded:i,failed:e,skipped:a}),{total:A.length,succeeded:i,failed:e,skipped:a,entries:E}}getCacheStats(){const A=Array.from(this.cache.entries()),B=Date.now(),I=A.filter(([,Q])=>B-Q.timestamp<Q.ttl).map(([Q])=>Q);return{size:I.length,txIds:I,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(Q=>!Q.success).length/B.length,totalChecks:B.length}}getAverageResponseTime(A){const B=this.healthData.get(A);return!B||B.length===0?0:B.reduce((I,Q)=>I+Q.responseTime,0)/B.length}recordGatewayResponse(A,B,I){this.healthData.has(A)||this.healthData.set(A,[]);const Q=this.healthData.get(A);Q.push({responseTime:B,success:I,timestamp:Date.now()}),Q.length>this.MAX_HEALTH_RECORDS&&Q.shift()}reportFetchTiming(A,B,I){this.recordGatewayResponse(A,B,I),this.logger.debug("Fetch timing reported",{host:A,timingMs:B,success:I})}getGatewayHealth(A){const B=this.gateways.find(s=>s.host===A);if(!B)return;const I=this.healthData.get(A)||[],Q=this.originalPriorities.get(A)??B.priority;if(I.length===0)return{host:A,priority:B.priority,originalPriority:Q,successCount:0,failureCount:0,totalChecks:0,successRate:0,averageResponseTime:0,lastSuccess:null,lastFailure:null,isHealthy:!0};const E=I.filter(s=>s.success).length,i=I.filter(s=>!s.success).length,e=E/I.length,a=Math.round(I.reduce((s,n)=>s+n.responseTime,0)/I.length),C=I.filter(s=>s.success).pop()?.timestamp??null,o=I.filter(s=>!s.success).pop()?.timestamp??null,t=e>=.5;return{host:A,priority:B.priority,originalPriority:Q,successCount:E,failureCount:i,totalChecks:I.length,successRate:e,averageResponseTime:a,lastSuccess:C,lastFailure:o,isHealthy:t}}getAllGatewayHealth(){return this.gateways.map(A=>this.getGatewayHealth(A.host))}adjustGatewayPriorities(A){const B=A?.minChecks??3,I=A?.healthyThreshold??.5,E=this.getAllGatewayHealth().reduce((C,o)=>C+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((C,o)=>({gateway:C,originalIndex:o}));i.sort((C,o)=>{const t=this.getGatewayHealth(C.gateway.host),s=this.getGatewayHealth(o.gateway.host),n=t.successRate>=I||t.totalChecks===0,r=s.successRate>=I||s.totalChecks===0;if(n&&!r)return-1;if(!n&&r)return 1;if(t.totalChecks>0&&s.totalChecks>0){const c=t.averageResponseTime-s.averageResponseTime;if(Math.abs(c)>100)return c}if(t.totalChecks>0&&s.totalChecks>0){const c=s.successRate-t.successRate;if(Math.abs(c)>.1)return c}return C.originalIndex-o.originalIndex});const e=i.map(C=>C.gateway),a=Math.min(...Array.from(this.originalPriorities.values()));return e.forEach((C,o)=>{C.priority=a+o}),this.gateways=e,this.logger.info("Gateway priorities adjusted",{newOrder:this.gateways.map(C=>({host:C.host,priority:C.priority,health:this.getGatewayHealth(C.host)}))}),[...this.gateways]}async runHealthCheck(A){const B=Date.now(),I=A?.txId??"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk012345",Q=A?.healthyThreshold??.5;A?.fastThreshold,this.logger.info("Starting gateway health check",{txId:I,gateways:this.gateways.map(r=>r.host)});const E=this.gateways.map(async r=>{const c=Date.now();let G=!1,D=this.timeout;try{const h=VB(I,r),w=new AbortController,y=setTimeout(()=>w.abort(),this.timeout),R=await fetch(h,{method:"HEAD",mode:"cors",signal:w.signal});clearTimeout(y),D=Date.now()-c,G=R.ok||R.status>=200&&R.status<400}catch{D=Date.now()-c,G=!1}return this.recordGatewayResponse(r.host,D,G),{host:r.host,success:G,responseTime:D}}),i=await Promise.all(E),e=this.getAllGatewayHealth(),a=[],C=[];let o=null,t=1/0;for(const r of i){const c=e.find(G=>G.host===r.host);r.success&&r.responseTime<t&&(t=r.responseTime,o=r.host),(c.successRate>=Q||c.totalChecks===1)&&r.success?a.push(r.host):C.push(r.host)}const s=Date.now()-B;A?.adjustPriorities&&this.adjustGatewayPriorities({minChecks:A.minChecksForAdjustment??1,healthyThreshold:Q});const n={timestamp:B,gateways:e,healthyGateways:a,unhealthyGateways:C,fastestGateway:o,totalTime:s};return this.logger.info("Health check complete",{healthyGateways:a,unhealthyGateways:C,fastestGateway:o,totalTime:s}),n}resetGatewayPriorities(){this.gateways.forEach(A=>{const B=this.originalPriorities.get(A.host);B!==void 0&&(A.priority=B)}),this.gateways.sort((A,B)=>{const I=this.originalPriorities.get(A.host)??A.priority,Q=this.originalPriorities.get(B.host)??B.priority;return I-Q}),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 TA=new GD,Ni=["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"],hD="ipfs.io",Eo="/ipfs/";function lD(g){if(!g||typeof g!="string")return null;if(g.startsWith("ipfs://ipfs/"))return g.slice(12);if(g.startsWith("ipfs://"))return g.slice(7);try{const A=new URL(g),{hostname:B,pathname:I}=A,Q=B.match(/^([A-Za-z0-9]+)\.ipfs\.dweb\.link$/);if(Q)return`${Q[1]}${I}`;if(Ni.some(i=>B===i||B.endsWith("."+i))&&I.startsWith(Eo))return I.slice(Eo.length)}catch{}return null}function hZ(g){if(!g||typeof g!="string")return!1;if(g.startsWith("ipfs://"))return!0;try{const A=new URL(g),{hostname:B,pathname:I}=A;if(/^[A-Za-z0-9]+\.ipfs\.dweb\.link$/.test(B)||Ni.some(E=>B===E||B.endsWith("."+E))&&I.startsWith(Eo))return!0}catch{}return!1}function lZ(g){if(!(!g||g.startsWith("ipfs://")))try{const{hostname:A}=new URL(g);return Ni.some(I=>A===I||A.endsWith("."+I))?A:void 0}catch{return}}function DZ(g,A={}){if(!g)return g;const B=typeof A=="string"?{gatewayHost:A}:A,{gatewayHost:I=hD,preserveOriginalGateway:Q=!1}=B,E=lD(g);if(E){if(Q){const i=lZ(g);if(i)return`https://${i}/ipfs/${E}`}return`https://${I}/ipfs/${E}`}return g}function Wi(g){throw new Error('Could not dynamically require "'+g+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var io={exports:{}};var DD;function dZ(){return DD||(DD=1,(function(g,A){(function(B){g.exports=B()})(function(){return(function B(I,Q,E){function i(C,o){if(!Q[C]){if(!I[C]){var t=typeof Wi=="function"&&Wi;if(!o&&t)return t(C,!0);if(e)return e(C,!0);var s=new Error("Cannot find module '"+C+"'");throw s.code="MODULE_NOT_FOUND",s}var n=Q[C]={exports:{}};I[C][0].call(n.exports,function(r){var c=I[C][1][r];return i(c||r)},n,n.exports,B,I,Q,E)}return Q[C].exports}for(var e=typeof Wi=="function"&&Wi,a=0;a<E.length;a++)i(E[a]);return i})({1:[function(B,I,Q){(function(E){var i=E.MutationObserver||E.WebKitMutationObserver,e;if(i){var a=0,C=new i(r),o=E.document.createTextNode("");C.observe(o,{characterData:!0}),e=function(){o.data=a=++a%2}}else if(!E.setImmediate&&typeof E.MessageChannel<"u"){var t=new E.MessageChannel;t.port1.onmessage=r,e=function(){t.port2.postMessage(0)}}else"document"in E&&"onreadystatechange"in E.document.createElement("script")?e=function(){var G=E.document.createElement("script");G.onreadystatechange=function(){r(),G.onreadystatechange=null,G.parentNode.removeChild(G),G=null},E.document.documentElement.appendChild(G)}:e=function(){setTimeout(r,0)};var s,n=[];function r(){s=!0;for(var G,D,h=n.length;h;){for(D=n,n=[],G=-1;++G<h;)D[G]();h=n.length}s=!1}I.exports=c;function c(G){n.push(G)===1&&!s&&e()}}).call(this,typeof Ei<"u"?Ei:typeof self<"u"?self:typeof window<"u"?window:{})},{}],2:[function(B,I,Q){var E=B(1);function i(){}var e={},a=["REJECTED"],C=["FULFILLED"],o=["PENDING"];I.exports=t;function t(R){if(typeof R!="function")throw new TypeError("resolver must be a function");this.state=o,this.queue=[],this.outcome=void 0,R!==i&&c(this,R)}t.prototype.catch=function(R){return this.then(null,R)},t.prototype.then=function(R,Y){if(typeof R!="function"&&this.state===C||typeof Y!="function"&&this.state===a)return this;var k=new this.constructor(i);if(this.state!==o){var W=this.state===C?R:Y;n(k,W,this.outcome)}else this.queue.push(new s(k,R,Y));return k};function s(R,Y,k){this.promise=R,typeof Y=="function"&&(this.onFulfilled=Y,this.callFulfilled=this.otherCallFulfilled),typeof k=="function"&&(this.onRejected=k,this.callRejected=this.otherCallRejected)}s.prototype.callFulfilled=function(R){e.resolve(this.promise,R)},s.prototype.otherCallFulfilled=function(R){n(this.promise,this.onFulfilled,R)},s.prototype.callRejected=function(R){e.reject(this.promise,R)},s.prototype.otherCallRejected=function(R){n(this.promise,this.onRejected,R)};function n(R,Y,k){E(function(){var W;try{W=Y(k)}catch(j){return e.reject(R,j)}W===R?e.reject(R,new TypeError("Cannot resolve promise with itself")):e.resolve(R,W)})}e.resolve=function(R,Y){var k=G(r,Y);if(k.status==="error")return e.reject(R,k.value);var W=k.value;if(W)c(R,W);else{R.state=C,R.outcome=Y;for(var j=-1,X=R.queue.length;++j<X;)R.queue[j].callFulfilled(Y)}return R},e.reject=function(R,Y){R.state=a,R.outcome=Y;for(var k=-1,W=R.queue.length;++k<W;)R.queue[k].callRejected(Y);return R};function r(R){var Y=R&&R.then;if(R&&(typeof R=="object"||typeof R=="function")&&typeof Y=="function")return function(){Y.apply(R,arguments)}}function c(R,Y){var k=!1;function W(QA){k||(k=!0,e.reject(R,QA))}function j(QA){k||(k=!0,e.resolve(R,QA))}function X(){Y(j,W)}var z=G(X);z.status==="error"&&W(z.value)}function G(R,Y){var k={};try{k.value=R(Y),k.status="success"}catch(W){k.status="error",k.value=W}return k}t.resolve=D;function D(R){return R instanceof this?R:e.resolve(new this(i),R)}t.reject=h;function h(R){var Y=new this(i);return e.reject(Y,R)}t.all=w;function w(R){var Y=this;if(Object.prototype.toString.call(R)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=R.length,W=!1;if(!k)return this.resolve([]);for(var j=new Array(k),X=0,z=-1,QA=new this(i);++z<k;)CA(R[z],z);return QA;function CA(dA,uA){Y.resolve(dA).then(AA,function(EA){W||(W=!0,e.reject(QA,EA))});function AA(EA){j[uA]=EA,++X===k&&!W&&(W=!0,e.resolve(QA,j))}}}t.race=y;function y(R){var Y=this;if(Object.prototype.toString.call(R)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=R.length,W=!1;if(!k)return this.resolve([]);for(var j=-1,X=new this(i);++j<k;)z(R[j]);return X;function z(QA){Y.resolve(QA).then(function(CA){W||(W=!0,e.resolve(X,CA))},function(CA){W||(W=!0,e.reject(X,CA))})}}},{1:1}],3:[function(B,I,Q){(function(E){typeof E.Promise!="function"&&(E.Promise=B(2))}).call(this,typeof Ei<"u"?Ei:typeof self<"u"?self:typeof window<"u"?window:{})},{2:2}],4:[function(B,I,Q){var E=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(F){return typeof F}:function(F){return F&&typeof Symbol=="function"&&F.constructor===Symbol&&F!==Symbol.prototype?"symbol":typeof F};function i(F,S){if(!(F instanceof S))throw new TypeError("Cannot call a class as a function")}function e(){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=e();function C(){try{if(!a||!a.open)return!1;var F=typeof openDatabase<"u"&&/(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&!/BlackBerry/.test(navigator.platform),S=typeof fetch=="function"&&fetch.toString().indexOf("[native code")!==-1;return(!F||S)&&typeof indexedDB<"u"&&typeof IDBKeyRange<"u"}catch{return!1}}function o(F,S){F=F||[],S=S||{};try{return new Blob(F,S)}catch(p){if(p.name!=="TypeError")throw p;for(var u=typeof BlobBuilder<"u"?BlobBuilder:typeof MSBlobBuilder<"u"?MSBlobBuilder:typeof MozBlobBuilder<"u"?MozBlobBuilder:WebKitBlobBuilder,U=new u,f=0;f<F.length;f+=1)U.append(F[f]);return U.getBlob(S.type)}}typeof Promise>"u"&&B(3);var t=Promise;function s(F,S){S&&F.then(function(u){S(null,u)},function(u){S(u)})}function n(F,S,u){typeof S=="function"&&F.then(S),typeof u=="function"&&F.catch(u)}function r(F){return typeof F!="string"&&(console.warn(F+" used as a key, but it is not a string."),F=String(F)),F}function c(){if(arguments.length&&typeof arguments[arguments.length-1]=="function")return arguments[arguments.length-1]}var G="local-forage-detect-blob-support",D=void 0,h={},w=Object.prototype.toString,y="readonly",R="readwrite";function Y(F){for(var S=F.length,u=new ArrayBuffer(S),U=new Uint8Array(u),f=0;f<S;f++)U[f]=F.charCodeAt(f);return u}function k(F){return new t(function(S){var u=F.transaction(G,R),U=o([""]);u.objectStore(G).put(U,"key"),u.onabort=function(f){f.preventDefault(),f.stopPropagation(),S(!1)},u.oncomplete=function(){var f=navigator.userAgent.match(/Chrome\/(\d+)/),p=navigator.userAgent.match(/Edge\//);S(p||!f||parseInt(f[1],10)>=43)}}).catch(function(){return!1})}function W(F){return typeof D=="boolean"?t.resolve(D):k(F).then(function(S){return D=S,D})}function j(F){var S=h[F.name],u={};u.promise=new t(function(U,f){u.resolve=U,u.reject=f}),S.deferredOperations.push(u),S.dbReady?S.dbReady=S.dbReady.then(function(){return u.promise}):S.dbReady=u.promise}function X(F){var S=h[F.name],u=S.deferredOperations.pop();if(u)return u.resolve(),u.promise}function z(F,S){var u=h[F.name],U=u.deferredOperations.pop();if(U)return U.reject(S),U.promise}function QA(F,S){return new t(function(u,U){if(h[F.name]=h[F.name]||SA(),F.db)if(S)j(F),F.db.close();else return u(F.db);var f=[F.name];S&&f.push(F.version);var p=a.open.apply(a,f);S&&(p.onupgradeneeded=function(N){var H=p.result;try{H.createObjectStore(F.storeName),N.oldVersion<=1&&H.createObjectStore(G)}catch(x){if(x.name==="ConstraintError")console.warn('The database "'+F.name+'" has been upgraded from version '+N.oldVersion+" to version "+N.newVersion+', but the storage "'+F.storeName+'" already exists.');else throw x}}),p.onerror=function(N){N.preventDefault(),U(p.error)},p.onsuccess=function(){var N=p.result;N.onversionchange=function(H){H.target.close()},u(N),X(F)}})}function CA(F){return QA(F,!1)}function dA(F){return QA(F,!0)}function uA(F,S){if(!F.db)return!0;var u=!F.db.objectStoreNames.contains(F.storeName),U=F.version<F.db.version,f=F.version>F.db.version;if(U&&(F.version!==S&&console.warn('The database "'+F.name+`" can't be downgraded from version `+F.db.version+" to version "+F.version+"."),F.version=F.db.version),f||u){if(u){var p=F.db.version+1;p>F.version&&(F.version=p)}return!0}return!1}function AA(F){return new t(function(S,u){var U=new FileReader;U.onerror=u,U.onloadend=function(f){var p=btoa(f.target.result||"");S({__local_forage_encoded_blob:!0,data:p,type:F.type})},U.readAsBinaryString(F)})}function EA(F){var S=Y(atob(F.data));return o([S],{type:F.type})}function ZA(F){return F&&F.__local_forage_encoded_blob}function NA(F){var S=this,u=S._initReady().then(function(){var U=h[S._dbInfo.name];if(U&&U.dbReady)return U.dbReady});return n(u,F,F),u}function Pa(F){j(F);for(var S=h[F.name],u=S.forages,U=0;U<u.length;U++){var f=u[U];f._dbInfo.db&&(f._dbInfo.db.close(),f._dbInfo.db=null)}return F.db=null,CA(F).then(function(p){return F.db=p,uA(F)?dA(F):p}).then(function(p){F.db=S.db=p;for(var N=0;N<u.length;N++)u[N]._dbInfo.db=p}).catch(function(p){throw z(F,p),p})}function aA(F,S,u,U){U===void 0&&(U=1);try{var f=F.db.transaction(F.storeName,S);u(null,f)}catch(p){if(U>0&&(!F.db||p.name==="InvalidStateError"||p.name==="NotFoundError"))return t.resolve().then(function(){if(!F.db||p.name==="NotFoundError"&&!F.db.objectStoreNames.contains(F.storeName)&&F.version<=F.db.version)return F.db&&(F.version=F.db.version+1),dA(F)}).then(function(){return Pa(F).then(function(){aA(F,S,u,U-1)})}).catch(u);u(p)}}function SA(){return{forages:[],db:null,dbReady:null,deferredOperations:[]}}function uI(F){var S=this,u={db:null};if(F)for(var U in F)u[U]=F[U];var f=h[u.name];f||(f=SA(),h[u.name]=f),f.forages.push(S),S._initReady||(S._initReady=S.ready,S.ready=NA);var p=[];function N(){return t.resolve()}for(var H=0;H<f.forages.length;H++){var x=f.forages[H];x!==S&&p.push(x._initReady().catch(N))}var q=f.forages.slice(0);return t.all(p).then(function(){return u.db=f.db,CA(u)}).then(function(V){return u.db=V,uA(u,S._defaultConfig.version)?dA(u):V}).then(function(V){u.db=f.db=V,S._dbInfo=u;for(var $=0;$<q.length;$++){var oA=q[$];oA!==S&&(oA._dbInfo.db=u.db,oA._dbInfo.version=u.version)}})}function kG(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){aA(u._dbInfo,y,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=x.get(F);q.onsuccess=function(){var V=q.result;V===void 0&&(V=null),ZA(V)&&(V=EA(V)),f(V)},q.onerror=function(){p(q.error)}}catch(V){p(V)}})}).catch(p)});return s(U,S),U}function yb(F,S){var u=this,U=new t(function(f,p){u.ready().then(function(){aA(u._dbInfo,y,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=x.openCursor(),V=1;q.onsuccess=function(){var $=q.result;if($){var oA=$.value;ZA(oA)&&(oA=EA(oA));var hA=F(oA,$.key,V++);hA!==void 0?f(hA):$.continue()}else f()},q.onerror=function(){p(q.error)}}catch($){p($)}})}).catch(p)});return s(U,S),U}function A4(F,S,u){var U=this;F=r(F);var f=new t(function(p,N){var H;U.ready().then(function(){return H=U._dbInfo,w.call(S)==="[object Blob]"?W(H.db).then(function(x){return x?S:AA(S)}):S}).then(function(x){aA(U._dbInfo,R,function(q,V){if(q)return N(q);try{var $=V.objectStore(U._dbInfo.storeName);x===null&&(x=void 0);var oA=$.put(x,F);V.oncomplete=function(){x===void 0&&(x=null),p(x)},V.onabort=V.onerror=function(){var hA=oA.error?oA.error:oA.transaction.error;N(hA)}}catch(hA){N(hA)}})}).catch(N)});return s(f,u),f}function B4(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){aA(u._dbInfo,R,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=x.delete(F);H.oncomplete=function(){f()},H.onerror=function(){p(q.error)},H.onabort=function(){var V=q.error?q.error:q.transaction.error;p(V)}}catch(V){p(V)}})}).catch(p)});return s(U,S),U}function g4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){aA(S._dbInfo,R,function(p,N){if(p)return f(p);try{var H=N.objectStore(S._dbInfo.storeName),x=H.clear();N.oncomplete=function(){U()},N.onabort=N.onerror=function(){var q=x.error?x.error:x.transaction.error;f(q)}}catch(q){f(q)}})}).catch(f)});return s(u,F),u}function I4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){aA(S._dbInfo,y,function(p,N){if(p)return f(p);try{var H=N.objectStore(S._dbInfo.storeName),x=H.count();x.onsuccess=function(){U(x.result)},x.onerror=function(){f(x.error)}}catch(q){f(q)}})}).catch(f)});return s(u,F),u}function Q4(F,S){var u=this,U=new t(function(f,p){if(F<0){f(null);return}u.ready().then(function(){aA(u._dbInfo,y,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=!1,V=x.openKeyCursor();V.onsuccess=function(){var $=V.result;if(!$){f(null);return}F===0||q?f($.key):(q=!0,$.advance(F))},V.onerror=function(){p(V.error)}}catch($){p($)}})}).catch(p)});return s(U,S),U}function E4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){aA(S._dbInfo,y,function(p,N){if(p)return f(p);try{var H=N.objectStore(S._dbInfo.storeName),x=H.openKeyCursor(),q=[];x.onsuccess=function(){var V=x.result;if(!V){U(q);return}q.push(V.key),V.continue()},x.onerror=function(){f(x.error)}}catch(V){f(V)}})}).catch(f)});return s(u,F),u}function i4(F,S){S=c.apply(this,arguments);var u=this.config();F=typeof F!="function"&&F||{},F.name||(F.name=F.name||u.name,F.storeName=F.storeName||u.storeName);var U=this,f;if(!F.name)f=t.reject("Invalid arguments");else{var p=F.name===u.name&&U._dbInfo.db,N=p?t.resolve(U._dbInfo.db):CA(F).then(function(H){var x=h[F.name],q=x.forages;x.db=H;for(var V=0;V<q.length;V++)q[V]._dbInfo.db=H;return H});F.storeName?f=N.then(function(H){if(H.objectStoreNames.contains(F.storeName)){var x=H.version+1;j(F);var q=h[F.name],V=q.forages;H.close();for(var $=0;$<V.length;$++){var oA=V[$];oA._dbInfo.db=null,oA._dbInfo.version=x}var hA=new t(function(DA,LA){var WA=a.open(F.name,x);WA.onerror=function(xB){var PE=WA.result;PE.close(),LA(xB)},WA.onupgradeneeded=function(){var xB=WA.result;xB.deleteObjectStore(F.storeName)},WA.onsuccess=function(){var xB=WA.result;xB.close(),DA(xB)}});return hA.then(function(DA){q.db=DA;for(var LA=0;LA<V.length;LA++){var WA=V[LA];WA._dbInfo.db=DA,X(WA._dbInfo)}}).catch(function(DA){throw(z(F,DA)||t.resolve()).catch(function(){}),DA})}}):f=N.then(function(H){j(F);var x=h[F.name],q=x.forages;H.close();for(var V=0;V<q.length;V++){var $=q[V];$._dbInfo.db=null}var oA=new t(function(hA,DA){var LA=a.deleteDatabase(F.name);LA.onerror=function(){var WA=LA.result;WA&&WA.close(),DA(LA.error)},LA.onblocked=function(){console.warn('dropInstance blocked for database "'+F.name+'" until all open connections are closed')},LA.onsuccess=function(){var WA=LA.result;WA&&WA.close(),hA(WA)}});return oA.then(function(hA){x.db=hA;for(var DA=0;DA<q.length;DA++){var LA=q[DA];X(LA._dbInfo)}}).catch(function(hA){throw(z(F,hA)||t.resolve()).catch(function(){}),hA})})}return s(f,S),f}var e4={_driver:"asyncStorage",_initStorage:uI,_support:C(),iterate:yb,getItem:kG,setItem:A4,removeItem:B4,clear:g4,length:I4,key:Q4,keys:E4,dropInstance:i4};function a4(){return typeof openDatabase=="function"}var Tg="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",C4="~~local_forage_type~",ub=/^~~local_forage_type~([^~]+)~/,_a="__lfsc__:",ZG=_a.length,NG="arbf",WG="blob",mb="si08",Sb="ui08",bb="uic8",pb="si16",Yb="si32",Ub="ur16",fb="ui32",kb="fl32",Zb="fl64",Nb=ZG+NG.length,Wb=Object.prototype.toString;function Hb(F){var S=F.length*.75,u=F.length,U,f=0,p,N,H,x;F[F.length-1]==="="&&(S--,F[F.length-2]==="="&&S--);var q=new ArrayBuffer(S),V=new Uint8Array(q);for(U=0;U<u;U+=4)p=Tg.indexOf(F[U]),N=Tg.indexOf(F[U+1]),H=Tg.indexOf(F[U+2]),x=Tg.indexOf(F[U+3]),V[f++]=p<<2|N>>4,V[f++]=(N&15)<<4|H>>2,V[f++]=(H&3)<<6|x&63;return q}function HG(F){var S=new Uint8Array(F),u="",U;for(U=0;U<S.length;U+=3)u+=Tg[S[U]>>2],u+=Tg[(S[U]&3)<<4|S[U+1]>>4],u+=Tg[(S[U+1]&15)<<2|S[U+2]>>6],u+=Tg[S[U+2]&63];return S.length%3===2?u=u.substring(0,u.length-1)+"=":S.length%3===1&&(u=u.substring(0,u.length-2)+"=="),u}function o4(F,S){var u="";if(F&&(u=Wb.call(F)),F&&(u==="[object ArrayBuffer]"||F.buffer&&Wb.call(F.buffer)==="[object ArrayBuffer]")){var U,f=_a;F instanceof ArrayBuffer?(U=F,f+=NG):(U=F.buffer,u==="[object Int8Array]"?f+=mb:u==="[object Uint8Array]"?f+=Sb:u==="[object Uint8ClampedArray]"?f+=bb:u==="[object Int16Array]"?f+=pb:u==="[object Uint16Array]"?f+=Ub:u==="[object Int32Array]"?f+=Yb:u==="[object Uint32Array]"?f+=fb:u==="[object Float32Array]"?f+=kb:u==="[object Float64Array]"?f+=Zb:S(new Error("Failed to get type for BinaryArray"))),S(f+HG(U))}else if(u==="[object Blob]"){var p=new FileReader;p.onload=function(){var N=C4+F.type+"~"+HG(this.result);S(_a+WG+N)},p.readAsArrayBuffer(F)}else try{S(JSON.stringify(F))}catch(N){console.error("Couldn't convert value into a JSON string: ",F),S(null,N)}}function t4(F){if(F.substring(0,ZG)!==_a)return JSON.parse(F);var S=F.substring(Nb),u=F.substring(ZG,Nb),U;if(u===WG&&ub.test(S)){var f=S.match(ub);U=f[1],S=S.substring(f[0].length)}var p=Hb(S);switch(u){case NG:return p;case WG:return o([p],{type:U});case mb:return new Int8Array(p);case Sb:return new Uint8Array(p);case bb:return new Uint8ClampedArray(p);case pb:return new Int16Array(p);case Ub:return new Uint16Array(p);case Yb:return new Int32Array(p);case fb:return new Uint32Array(p);case kb:return new Float32Array(p);case Zb:return new Float64Array(p);default:throw new Error("Unkown type: "+u)}}var JG={serialize:o4,deserialize:t4,stringToBuffer:Hb,bufferToString:HG};function Jb(F,S,u,U){F.executeSql("CREATE TABLE IF NOT EXISTS "+S.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],u,U)}function s4(F){var S=this,u={db:null};if(F)for(var U in F)u[U]=typeof F[U]!="string"?F[U].toString():F[U];var f=new t(function(p,N){try{u.db=openDatabase(u.name,String(u.version),u.description,u.size)}catch(H){return N(H)}u.db.transaction(function(H){Jb(H,u,function(){S._dbInfo=u,p()},function(x,q){N(q)})},N)});return u.serializer=JG,f}function Og(F,S,u,U,f,p){F.executeSql(u,U,f,function(N,H){H.code===H.SYNTAX_ERR?N.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?",[S.storeName],function(x,q){q.rows.length?p(x,H):Jb(x,S,function(){x.executeSql(u,U,f,p)},p)},p):p(N,H)},p)}function n4(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"SELECT * FROM "+N.storeName+" WHERE key = ? LIMIT 1",[F],function(x,q){var V=q.rows.length?q.rows.item(0).value:null;V&&(V=N.serializer.deserialize(V)),f(V)},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function r4(F,S){var u=this,U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"SELECT * FROM "+N.storeName,[],function(x,q){for(var V=q.rows,$=V.length,oA=0;oA<$;oA++){var hA=V.item(oA),DA=hA.value;if(DA&&(DA=N.serializer.deserialize(DA)),DA=F(DA,hA.key,oA+1),DA!==void 0){f(DA);return}}f()},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function xb(F,S,u,U){var f=this;F=r(F);var p=new t(function(N,H){f.ready().then(function(){S===void 0&&(S=null);var x=S,q=f._dbInfo;q.serializer.serialize(S,function(V,$){$?H($):q.db.transaction(function(oA){Og(oA,q,"INSERT OR REPLACE INTO "+q.storeName+" (key, value) VALUES (?, ?)",[F,V],function(){N(x)},function(hA,DA){H(DA)})},function(oA){if(oA.code===oA.QUOTA_ERR){if(U>0){N(xb.apply(f,[F,x,u,U-1]));return}H(oA)}})})}).catch(H)});return s(p,u),p}function c4(F,S,u){return xb.apply(this,[F,S,u,1])}function G4(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"DELETE FROM "+N.storeName+" WHERE key = ?",[F],function(){f()},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function h4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){var p=S._dbInfo;p.db.transaction(function(N){Og(N,p,"DELETE FROM "+p.storeName,[],function(){U()},function(H,x){f(x)})})}).catch(f)});return s(u,F),u}function l4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){var p=S._dbInfo;p.db.transaction(function(N){Og(N,p,"SELECT COUNT(key) as c FROM "+p.storeName,[],function(H,x){var q=x.rows.item(0).c;U(q)},function(H,x){f(x)})})}).catch(f)});return s(u,F),u}function D4(F,S){var u=this,U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"SELECT key FROM "+N.storeName+" WHERE id = ? LIMIT 1",[F+1],function(x,q){var V=q.rows.length?q.rows.item(0).key:null;f(V)},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function d4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){var p=S._dbInfo;p.db.transaction(function(N){Og(N,p,"SELECT key FROM "+p.storeName,[],function(H,x){for(var q=[],V=0;V<x.rows.length;V++)q.push(x.rows.item(V).key);U(q)},function(H,x){f(x)})})}).catch(f)});return s(u,F),u}function w4(F){return new t(function(S,u){F.transaction(function(U){U.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'",[],function(f,p){for(var N=[],H=0;H<p.rows.length;H++)N.push(p.rows.item(H).name);S({db:F,storeNames:N})},function(f,p){u(p)})},function(U){u(U)})})}function F4(F,S){S=c.apply(this,arguments);var u=this.config();F=typeof F!="function"&&F||{},F.name||(F.name=F.name||u.name,F.storeName=F.storeName||u.storeName);var U=this,f;return F.name?f=new t(function(p){var N;F.name===u.name?N=U._dbInfo.db:N=openDatabase(F.name,"","",0),F.storeName?p({db:N,storeNames:[F.storeName]}):p(w4(N))}).then(function(p){return new t(function(N,H){p.db.transaction(function(x){function q(hA){return new t(function(DA,LA){x.executeSql("DROP TABLE IF EXISTS "+hA,[],function(){DA()},function(WA,xB){LA(xB)})})}for(var V=[],$=0,oA=p.storeNames.length;$<oA;$++)V.push(q(p.storeNames[$]));t.all(V).then(function(){N()}).catch(function(hA){H(hA)})},function(x){H(x)})})}):f=t.reject("Invalid arguments"),s(f,S),f}var M4={_driver:"webSQLStorage",_initStorage:s4,_support:a4(),iterate:r4,getItem:n4,setItem:c4,removeItem:G4,clear:h4,length:l4,key:D4,keys:d4,dropInstance:F4};function R4(){try{return typeof localStorage<"u"&&"setItem"in localStorage&&!!localStorage.setItem}catch{return!1}}function qb(F,S){var u=F.name+"/";return F.storeName!==S.storeName&&(u+=F.storeName+"/"),u}function y4(){var F="_localforage_support_test";try{return localStorage.setItem(F,!0),localStorage.removeItem(F),!1}catch{return!0}}function u4(){return!y4()||localStorage.length>0}function m4(F){var S=this,u={};if(F)for(var U in F)u[U]=F[U];return u.keyPrefix=qb(F,S._defaultConfig),u4()?(S._dbInfo=u,u.serializer=JG,t.resolve()):t.reject()}function S4(F){var S=this,u=S.ready().then(function(){for(var U=S._dbInfo.keyPrefix,f=localStorage.length-1;f>=0;f--){var p=localStorage.key(f);p.indexOf(U)===0&&localStorage.removeItem(p)}});return s(u,F),u}function b4(F,S){var u=this;F=r(F);var U=u.ready().then(function(){var f=u._dbInfo,p=localStorage.getItem(f.keyPrefix+F);return p&&(p=f.serializer.deserialize(p)),p});return s(U,S),U}function p4(F,S){var u=this,U=u.ready().then(function(){for(var f=u._dbInfo,p=f.keyPrefix,N=p.length,H=localStorage.length,x=1,q=0;q<H;q++){var V=localStorage.key(q);if(V.indexOf(p)===0){var $=localStorage.getItem(V);if($&&($=f.serializer.deserialize($)),$=F($,V.substring(N),x++),$!==void 0)return $}}});return s(U,S),U}function Y4(F,S){var u=this,U=u.ready().then(function(){var f=u._dbInfo,p;try{p=localStorage.key(F)}catch{p=null}return p&&(p=p.substring(f.keyPrefix.length)),p});return s(U,S),U}function U4(F){var S=this,u=S.ready().then(function(){for(var U=S._dbInfo,f=localStorage.length,p=[],N=0;N<f;N++){var H=localStorage.key(N);H.indexOf(U.keyPrefix)===0&&p.push(H.substring(U.keyPrefix.length))}return p});return s(u,F),u}function f4(F){var S=this,u=S.keys().then(function(U){return U.length});return s(u,F),u}function k4(F,S){var u=this;F=r(F);var U=u.ready().then(function(){var f=u._dbInfo;localStorage.removeItem(f.keyPrefix+F)});return s(U,S),U}function Z4(F,S,u){var U=this;F=r(F);var f=U.ready().then(function(){S===void 0&&(S=null);var p=S;return new t(function(N,H){var x=U._dbInfo;x.serializer.serialize(S,function(q,V){if(V)H(V);else try{localStorage.setItem(x.keyPrefix+F,q),N(p)}catch($){($.name==="QuotaExceededError"||$.name==="NS_ERROR_DOM_QUOTA_REACHED")&&H($),H($)}})})});return s(f,u),f}function N4(F,S){if(S=c.apply(this,arguments),F=typeof F!="function"&&F||{},!F.name){var u=this.config();F.name=F.name||u.name,F.storeName=F.storeName||u.storeName}var U=this,f;return F.name?f=new t(function(p){F.storeName?p(qb(F,U._defaultConfig)):p(F.name+"/")}).then(function(p){for(var N=localStorage.length-1;N>=0;N--){var H=localStorage.key(N);H.indexOf(p)===0&&localStorage.removeItem(H)}}):f=t.reject("Invalid arguments"),s(f,S),f}var W4={_driver:"localStorageWrapper",_initStorage:m4,_support:R4(),iterate:p4,getItem:b4,setItem:Z4,removeItem:k4,clear:S4,length:f4,key:Y4,keys:U4,dropInstance:N4},H4=function(S,u){return S===u||typeof S=="number"&&typeof u=="number"&&isNaN(S)&&isNaN(u)},J4=function(S,u){for(var U=S.length,f=0;f<U;){if(H4(S[f],u))return!0;f++}return!1},Lb=Array.isArray||function(F){return Object.prototype.toString.call(F)==="[object Array]"},jE={},Vb={},YQ={INDEXEDDB:e4,WEBSQL:M4,LOCALSTORAGE:W4},x4=[YQ.INDEXEDDB._driver,YQ.WEBSQL._driver,YQ.LOCALSTORAGE._driver],$a=["dropInstance"],xG=["clear","getItem","iterate","key","keys","length","removeItem","setItem"].concat($a),q4={description:"",driver:x4.slice(),name:"localforage",size:4980736,storeName:"keyvaluepairs",version:1};function L4(F,S){F[S]=function(){var u=arguments;return F.ready().then(function(){return F[S].apply(F,u)})}}function qG(){for(var F=1;F<arguments.length;F++){var S=arguments[F];if(S)for(var u in S)S.hasOwnProperty(u)&&(Lb(S[u])?arguments[0][u]=S[u].slice():arguments[0][u]=S[u])}return arguments[0]}var V4=(function(){function F(S){i(this,F);for(var u in YQ)if(YQ.hasOwnProperty(u)){var U=YQ[u],f=U._driver;this[u]=f,jE[f]||this.defineDriver(U)}this._defaultConfig=qG({},q4),this._config=qG({},this._defaultConfig,S),this._driverSet=null,this._initDriver=null,this._ready=!1,this._dbInfo=null,this._wrapLibraryMethodsWithReady(),this.setDriver(this._config.driver).catch(function(){})}return F.prototype.config=function(u){if((typeof u>"u"?"undefined":E(u))==="object"){if(this._ready)return new Error("Can't call config() after localforage has been used.");for(var U in u){if(U==="storeName"&&(u[U]=u[U].replace(/\W/g,"_")),U==="version"&&typeof u[U]!="number")return new Error("Database version must be a number.");this._config[U]=u[U]}return"driver"in u&&u.driver?this.setDriver(this._config.driver):!0}else return typeof u=="string"?this._config[u]:this._config},F.prototype.defineDriver=function(u,U,f){var p=new t(function(N,H){try{var x=u._driver,q=new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver");if(!u._driver){H(q);return}for(var V=xG.concat("_initStorage"),$=0,oA=V.length;$<oA;$++){var hA=V[$],DA=!J4($a,hA);if((DA||u[hA])&&typeof u[hA]!="function"){H(q);return}}var LA=function(){for(var PE=function(K4){return function(){var z4=new Error("Method "+K4+" is not implemented by the current driver"),vb=t.reject(z4);return s(vb,arguments[arguments.length-1]),vb}},LG=0,X4=$a.length;LG<X4;LG++){var VG=$a[LG];u[VG]||(u[VG]=PE(VG))}};LA();var WA=function(PE){jE[x]&&console.info("Redefining LocalForage driver: "+x),jE[x]=u,Vb[x]=PE,N()};"_support"in u?u._support&&typeof u._support=="function"?u._support().then(WA,H):WA(!!u._support):WA(!0)}catch(xB){H(xB)}});return n(p,U,f),p},F.prototype.driver=function(){return this._driver||null},F.prototype.getDriver=function(u,U,f){var p=jE[u]?t.resolve(jE[u]):t.reject(new Error("Driver not found."));return n(p,U,f),p},F.prototype.getSerializer=function(u){var U=t.resolve(JG);return n(U,u),U},F.prototype.ready=function(u){var U=this,f=U._driverSet.then(function(){return U._ready===null&&(U._ready=U._initDriver()),U._ready});return n(f,u,u),f},F.prototype.setDriver=function(u,U,f){var p=this;Lb(u)||(u=[u]);var N=this._getSupportedDrivers(u);function H(){p._config.driver=p.driver()}function x($){return p._extend($),H(),p._ready=p._initStorage(p._config),p._ready}function q($){return function(){var oA=0;function hA(){for(;oA<$.length;){var DA=$[oA];return oA++,p._dbInfo=null,p._ready=null,p.getDriver(DA).then(x).catch(hA)}H();var LA=new Error("No available storage method found.");return p._driverSet=t.reject(LA),p._driverSet}return hA()}}var V=this._driverSet!==null?this._driverSet.catch(function(){return t.resolve()}):t.resolve();return this._driverSet=V.then(function(){var $=N[0];return p._dbInfo=null,p._ready=null,p.getDriver($).then(function(oA){p._driver=oA._driver,H(),p._wrapLibraryMethodsWithReady(),p._initDriver=q(N)})}).catch(function(){H();var $=new Error("No available storage method found.");return p._driverSet=t.reject($),p._driverSet}),n(this._driverSet,U,f),this._driverSet},F.prototype.supports=function(u){return!!Vb[u]},F.prototype._extend=function(u){qG(this,u)},F.prototype._getSupportedDrivers=function(u){for(var U=[],f=0,p=u.length;f<p;f++){var N=u[f];this.supports(N)&&U.push(N)}return U},F.prototype._wrapLibraryMethodsWithReady=function(){for(var u=0,U=xG.length;u<U;u++)L4(this,xG[u])},F.prototype.createInstance=function(u){return new F(u)},F})(),v4=new V4;I.exports=v4},{3:3}]},{},[4])(4)})})(io)),io.exports}var wZ=dZ();const FZ=dh(wZ);function JI(g){return`model:${g}`}function MZ(g){const A=g.lastIndexOf("/");return A>=0?g.substring(0,A+1):""}async function RZ(g,A=3,B=1e3){let I=null;for(let Q=0;Q<A;Q++)try{const E=await fetch(g);if(!E.ok)throw new Error(`HTTP ${E.status}: ${E.statusText}`);return E}catch(E){if(I=E,Q===A-1)throw E;const i=B*Math.pow(2,Q);console.warn(`[ModelCache] Fetch failed (attempt ${Q+1}/${A}), retrying in ${i}ms...`,{url:g,error:String(E)}),await new Promise(e=>setTimeout(e,i))}throw I}async function dD(g,A,B,I=3,Q=1e3){let E=null;for(let i=0;i<I;i++){const e=A?await A(g):g;try{const a=await fetch(e);if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);const C=await a.text(),o=JSON.parse(C),t=MZ(e),s={},n=[];if(o.weightsManifest&&Array.isArray(o.weightsManifest)){for(const c of o.weightsManifest)if(c.paths&&Array.isArray(c.paths))for(const G of c.paths)n.push(G)}const r=n.map(async c=>{const G=t+c,D=await RZ(G,I,Q);s[c]=await D.arrayBuffer()});return await Promise.all(r),{manifest:C,weights:s,savedAt:Date.now(),originalUrl:g}}catch(a){if(E=a,i===I-1)throw a;B?.(g);const C=Q*Math.pow(2,i);console.warn(`[ModelCache] Model fetch failed (attempt ${i+1}/${I}), re-resolving and retrying in ${C}ms...`,{url:g,resolvedUrl:e,error:String(a)}),await new Promise(o=>setTimeout(o,C))}}throw E}function eo(g,A){return JSON.parse(A.manifest),{load:async()=>wD(A)}}function wD(g){const A=JSON.parse(g.manifest),B=[],I=[];if(A.weightsManifest&&Array.isArray(A.weightsManifest))for(const Q of A.weightsManifest){if(Q.weights&&Array.isArray(Q.weights))for(const E of Q.weights)I.push(E);if(Q.paths&&Array.isArray(Q.paths))for(const E of Q.paths){const i=g.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:I.length>0?I:void 0,weightData:B.length>0?B.length===1?B[0]:B:void 0}}const FD=new Map;let MD=!1;function yZ(){MD||(MD=!0,import("@tensorflow/tfjs").then(g=>{g.io.registerLoadRouter((A=>{if(typeof A=="string"&&A.startsWith("cached://")){const B=FD.get(A);if(B)return{load:async()=>{const I=await B.store.getItem(B.key);if(!I)throw new Error(`[ModelCache] Model not in cache: ${A}`);return wD(I)}}}return null}))}))}yZ();class RD{constructor(A={}){this.store=FZ.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(JI(A))!=null}async getCacheInfo(A){const B=await this.store.getItem(JI(A));if(!B)return{cached:!1};let I=B.manifest.length;for(const Q of Object.values(B.weights))I+=Q.byteLength;return{cached:!0,savedAt:B.savedAt,size:I}}async loadFromCache(A,B){const I=await this.store.getItem(JI(B));if(!I)throw new Error(`[ModelCache] Model not cached: ${B}`);return A.loadGraphModel(eo(A,I))}async getOrFetchGraphModel(A,B,I={}){const Q=JI(B);try{const i=await this.store.getItem(Q);if(i)return console.info(`[ModelCache] Loading model from cache: ${B}`),await A.loadGraphModel(eo(A,i))}catch(i){console.warn("[ModelCache] Cache load failed, clearing and re-fetching:",i),await this.store.removeItem(Q)}console.info(`[ModelCache] Downloading model: ${B}`);const E=await dD(B,I.resolveUrl,I.invalidateUrlCache,I.maxRetries??3,I.baseDelayMs??1e3);return await this.store.setItem(Q,E),console.info(`[ModelCache] Model cached: ${B} (${Object.keys(E.weights).length} shards)`),A.loadGraphModel(eo(A,E))}async getOrFetchEssentiaUrl(A,B={}){const I=JI(A),Q=`cached://${A}`;if(await this.store.getItem(I))console.info(`[ModelCache] Loading Essentia model from cache: ${A}`);else{console.info(`[ModelCache] Downloading model for Essentia: ${A}`);const i=await dD(A,B.resolveUrl,B.invalidateUrlCache,B.maxRetries??3,B.baseDelayMs??1e3);await this.store.setItem(I,i),console.info(`[ModelCache] Model cached: ${A} (${Object.keys(i.weights).length} shards)`)}return FD.set(Q,{store:this.store,key:I}),Q}async clear(A){A?(await this.store.removeItem(JI(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 I of Object.values(B.weights))A+=I.byteLength}}),A}}const xI=new RD;function uZ(g){if(!g||!g.metadata)return null;if(typeof g.metadata=="string")try{const A=JSON.parse(g.metadata);return typeof A=="object"&&A!==null&&!Array.isArray(A)?A:null}catch{return null}return typeof g.metadata=="object"&&!Array.isArray(g.metadata)?g.metadata:null}function yD(g){const A={stems:[],mixes:[],hasExtras:!1};if(!g)return A;const B=pZ(g),I=YZ(g),Q=typeof g.vrm=="string"?g.vrm:void 0,E=mZ(g.lyrics),i=uD(g.visualizer),e=uD(g.video),a=SZ(g.merch),C=bZ(g.credits),o=typeof g.midi=="string"?g.midi:void 0,t=typeof g.step_mania=="string"?g.step_mania:void 0,s=typeof g.clone_hero=="string"?g.clone_hero:void 0,n=typeof g.external_url=="string"?g.external_url:void 0;return{hasExtras:B.length>0||I.length>0||!!Q||!!E||!!i||!!e||!!a||!!C||!!o||!!t||!!s||!!n,...B.length>0?{stems:B}:{},...I.length>0?{mixes:I}:{},...Q?{vrm:Q}:{},...E?{lyrics:E}:{},...i?{visualizer:i}:{},...e?{video:e}:{},...a?{merch:a}:{},...C?{credits:C}:{},...o?{midi:o}:{},...t?{step_mania:t}:{},...s?{clone_hero:s}:{},...n?{external_url:n}:{}}}function mZ(g){if(g){if(typeof g=="string")return{text:g};if(typeof g=="object"&&!Array.isArray(g)){const A=g;return{text:typeof A.text=="string"?A.text:void 0}}}}function uD(g){if(!g||typeof g!="object"||Array.isArray(g))return;const A=g;if(typeof A.uri=="string")return{uri:A.uri,mime_type:typeof A.mime_type=="string"?A.mime_type:void 0}}function SZ(g){if(!g||typeof g!="object"||Array.isArray(g))return;const A=g;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 bZ(g){if(!Array.isArray(g))return;const A=[];for(const B of g)if(B&&typeof B=="object"){const I=B;typeof I.name=="string"&&typeof I.credit=="string"&&A.push({name:I.name,credit:I.credit})}return A.length>0?A:void 0}function pZ(g){const A=g.stems;if(!Array.isArray(A))return[];const B=[];for(const I of A)if(I&&typeof I=="object"){const Q=I;B.push({name:typeof Q.name=="string"?Q.name:"",uri:typeof Q.uri=="string"?Q.uri:void 0,mime_type:typeof Q.mime_type=="string"?Q.mime_type:void 0})}return B}function YZ(g){const A=g.mixes;if(!Array.isArray(A))return[];const B=[];for(const I of A)if(I&&typeof I=="object"){const Q=I,E=UZ(Q.name),i=fZ(Q.conditions);B.push({name:E||"",uri:typeof Q.uri=="string"?Q.uri:void 0,mime_type:typeof Q.mime_type=="string"?Q.mime_type:void 0,conditions:i})}return B}function UZ(g){if(typeof g=="string")return g;if(g&&typeof g=="object"&&!Array.isArray(g)){const A=g;if(typeof A.value=="string")return A.value}return""}function fZ(g){if(!Array.isArray(g))return[];const A=[];for(const B of g)if(B&&typeof B=="object"){const I=B;typeof I.type=="string"&&typeof I.value=="string"&&A.push({type:I.type,value:I.value})}return A}function kZ(g,A){const B=[],I=new Date;for(const Q of g.mixes||[]){if(Q.conditions.length===0){B.push({mix:Q,conditions:[],allMet:!0,unmetConditions:[]});continue}const E=[],i=[];for(const e of Q.conditions){const a=ZZ(e,A,I);E.push(a),a.met||i.push(a)}B.push({mix:Q,conditions:E,allMet:i.length===0,unmetConditions:i})}return B}function ZZ(g,A,B=new Date){const{type:I,value:Q}=g,E=A?.environment,i=A?.appState;switch(I){case"weather":{const e=E?.weather?.weatherType||"",a=e.toLowerCase()===Q.toLowerCase();return{type:I,value:Q,met:a,reason:a?`Weather is ${e}`:`Weather is ${e} (need ${Q})`}}case"day":{const a=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][B.getDay()],C=a.toLowerCase()===Q.toLowerCase();return{type:I,value:Q,met:C,reason:C?`Today is ${a}`:`Today is ${a} (need ${Q})`}}case"start_time":{const e=B.getHours()*60+B.getMinutes(),a=mD(Q),C=e>=a;return{type:I,value:Q,met:C,reason:C?`Time is after ${Q}`:`Time is before ${Q}`}}case"end_time":{const e=B.getHours()*60+B.getMinutes(),a=mD(Q),C=e<a;return{type:I,value:Q,met:C,reason:C?`Time is before ${Q}`:`Time is after ${Q}`}}case"min_plays":{const e=parseInt(Q,10),a=i?.playCount??0,C=a>=e;return{type:I,value:Q,met:C,reason:C?`Played ${a} times (need ${e})`:`Played ${a} times (need ${e})`}}case"max_plays":{const e=parseInt(Q,10),a=i?.playCount??0,C=a<=e;return{type:I,value:Q,met:C,reason:C?`Played ${a} times (max ${e})`:`Played ${a} times (exceeds max ${e})`}}case"every_x_plays":{const e=parseInt(Q,10),a=i?.playCount??0,C=e>0&&a>0&&a%e===0;return{type:I,value:Q,met:C,reason:C?`Play #${a} (every ${e} plays)`:`Play #${a} (not a multiple of ${e})`}}case"altitude":{const e=E?.geolocation?.altitude;if(e==null)return{type:I,value:Q,met:!1,reason:"Altitude unavailable"};const a=NZ(Q),C=WZ(e,a.operator,a.threshold);return{type:I,value:Q,met:C,reason:C?`Altitude ${e}m ${a.operator} ${a.threshold}m`:`Altitude ${e}m (need ${a.operator} ${a.threshold}m)`}}case"favorite":{const e=i?.isFavorite??!1,a=Q.toLowerCase()==="true",C=e===a;return{type:I,value:Q,met:C,reason:C?e?"Track is favorited":"Track is not favorited":e?"Track is favorited (need unfavorited)":"Track is not favorited (need favorited)"}}case"birthday":{if(!i?.userBirthday)return{type:I,value:Q,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:I,value:Q,met:a,reason:a?"It's your birthday!":`Not your birthday (need ${i.userBirthday})`}}case"weight":return{type:I,value:Q,met:!0,reason:`Weight ${Q} (used for random selection, always available)`};default:return{type:I,value:Q,met:!0,reason:`Custom condition: ${I} = ${Q}`}}}function mD(g){const A=g.split(":");if(A.length!==2)return 0;const B=parseInt(A[0],10),I=parseInt(A[1],10);return isNaN(B)||isNaN(I)?0:B*60+I}function NZ(g){const A=g.match(/^(>=|<=|>|<|=)?\s*(\d+(?:\.\d+)?)\s*$/);return A?{operator:A[1]||">=",threshold:parseFloat(A[2])}:{operator:">=",threshold:parseFloat(g)||0}}function WZ(g,A,B){switch(A){case">":return g>B;case">=":return g>=B;case"<":return g<B;case"<=":return g<=B;case"=":case"==":return g===B;default:return g>=B}}class SD{generateName(A,B,I,Q,E=!1){const i=this.cleanTitle(B.title),e=E?A:`${A}-${Date.now()}-${Math.random()}`,a=new qB(e);switch(this.selectFormat(a)){case"class_title":return this.formatClassTitle(i,Q,a);case"adjective_construct":return this.formatAdjectiveConstruct(i,B.genre,I,a);case"clan_construct":return this.formatClanConstruct(i,B.artist,a);case"descriptive_epithet":return this.formatDescriptiveEpithet(i,Q,I,a);case"compound_adjective":return this.formatCompoundAdjective(i,B.genre,I,a);case"artist_inspired":return this.formatArtistInspired(i,B.artist,Q,a);case"mononym_subtitle":return this.formatMononymSubtitle(i,I,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,I){return`${A} the ${B}`}formatAdjectiveConstruct(A,B,I,Q){const E=this.findGenreKey(B),i=jB.adjectives[E]||jB.adjectives.default,e=this.calculateBalancedAdjectiveWeights(I),a=Q.weightedChoice(e),C=i[a];return`${Q.randomChoice(C)} ${A}`}formatClanConstruct(A,B,I){return`${A} of ${B}`}formatDescriptiveEpithet(A,B,I,Q){const E=Q.randomChoice(jB.descriptors),i=jB.classAspects[B]||["Wanderer","Seeker","Sage","Hero"],e=Q.randomChoice(i);return`${A}, the ${E} ${e}`}formatCompoundAdjective(A,B,I,Q){const E=Q.randomChoice(jB.prefixes),i=Q.randomChoice(jB.suffixes);return`${E}-${i} ${A}`}formatArtistInspired(A,B,I,Q){const E=B.split(" ")[0],i=Q.randomChoice(jB.occupations),e=`${E}${i}`,a=Q.randomChoice(jB.realms);return`${e} of the ${a}`}formatMononymSubtitle(A,B,I,Q){const E=A.split(" "),i=E[0];let e;return E.length>1?e=E.slice(1).join(" "):e=Q.randomChoice(jB.subtitlePrefixes),`${i} [${e}]`}calculateBalancedAdjectiveWeights(A){const I={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+I.bass],["treble",1+I.treble],["mid",1+I.mid],["quiet",1+I.quiet],["loud",1+I.loud]]}findGenreKey(A){const B=A.toLowerCase(),I=Object.keys(jB.adjectives).filter(Q=>Q!=="default"&&B.includes(Q));return I.length>0?I[0]:"default"}}class uB{static select(A,B,I,Q="relative"){if(A.length===0)throw new Error("Cannot select from empty items array");const E=this.getFinalWeights(A,B,Q),i=A.map(e=>{const a=this.getItemKey(e),C=a in E?E[a]:1;return[e,C]});return I.weightedChoice(i)}static selectMultiple(A,B,I,Q,E="relative"){if(A.length===0)return[];if(Q<=0)return[];if(Q>=A.length)return I.shuffle(A);const i=[],e=[...A],a={...B};for(let C=0;C<Q&&e.length>0;C++){const o=this.select(e,a,I,E);i.push(o);const t=e.indexOf(o);if(t!==-1){const s=this.getItemKey(o);e.splice(t,1),delete a[s]}}return i}static getProbabilities(A,B,I="relative"){if(A.length===0)return{};const Q=this.getFinalWeights(A,B,I),E=Object.values(Q).reduce((e,a)=>e+a,0);if(E===0){const e={};for(const a of A){const C=this.getItemKey(a);e[C]=1/A.length}return e}const i={};for(const e of A){const a=this.getItemKey(e),C=Q[a]||0;i[a]=E>0?C/E:0}return i}static normalizeWeights(A,B,I="relative"){if(A.length===0)return{};const Q=uB.getFinalWeights(A,B,I),E=Object.values(Q).reduce((e,a)=>e+a,0);if(E===0){const e={};for(const a of A){const C=uB.getItemKey(a);e[C]=1/A.length}return e}const i={};for(const e of A){const a=uB.getItemKey(e);i[a]=Q[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,I){const Q={};if(I==="default")for(const E of A){const i=this.getItemKey(E);Q[i]=1}else if(I==="absolute")for(const E of A){const i=this.getItemKey(E);Q[i]=B[i]!==void 0?B[i]:1}else for(const E of A){const i=this.getItemKey(E);Q[i]=B[i]!==void 0?B[i]:1}return Q}}const ao=[{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"]}],Co=[{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"]}],oo=[{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."}],HZ=["physical","exploration","combat","criminal","subterfuge","knowledge","magic","environmental","social","perception","practical","entertainment"],JZ={"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 to(){const g=IA.getInstance();for(const[A,B]of Object.entries(JZ))g.initializeDefaults(A,[...B])}function bD(){return IA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("appearance."))}function so(){bD()||to()}const xZ=Object.values(yC),qZ=Object.entries(ni).map(([g,A])=>({class:g,cantrips:A.cantrips,spells_by_level:A.spells_by_level}));function no(){const g=IA.getInstance();g.initializeDefaults("spells",xZ);for(const A of qZ){const B=`spells.${A.class}`;g.initializeDefaults(B,[A])}}function pD(){return IA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("spells"))}function Hi(){pD()||no()}const LZ=Object.values(mI).map(g=>({...g,source:"default",spawnWeight:g.spawnWeight??1,tags:g.tags??[]}));function ro(){IA.getInstance().initializeDefaults("equipment",LZ)}function YD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="equipment")}function co(){YD()||ro()}function Go(){IA.getInstance().initializeDefaults("races",[..._h])}function UD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="races")}function ho(){UD()||Go()}function lo(){IA.getInstance().initializeDefaults("races.data",[...Bl])}function fD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="races.data")}function kD(){fD()||lo()}function Do(){IA.getInstance().initializeDefaults("classes",[...jh])}function ZD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="classes")}function wo(){ZD()||Do()}function VZ(){to(),no(),ro(),Go(),lo(),Do(),Fo(),Ro()}function vZ(){so(),Hi(),co(),ho(),kD(),wo(),Mo(),HD()}function Fo(){const g=IA.getInstance(),A={};for(const I of ao)A[I.class]||(A[I.class]=[]),A[I.class].push(I);g.initializeDefaults("classFeatures",[...ao]);for(const[I,Q]of Object.entries(A)){const E=`classFeatures.${I}`;g.initializeDefaults(E,Q)}const B={};for(const I of Co)B[I.race]||(B[I.race]=[]),B[I.race].push(I);g.initializeDefaults("racialTraits",[...Co]);for(const[I,Q]of Object.entries(B)){const E=`racialTraits.${I}`;g.initializeDefaults(E,Q)}}function ND(){return IA.getInstance().getRegisteredCategories().some(B=>B==="classFeatures"||B==="racialTraits")}function Mo(){ND()||Fo()}function Ro(){const g=IA.getInstance(),A={STR:[],DEX:[],CON:[],INT:[],WIS:[],CHA:[]};for(const B of oo)A[B.ability].push(B);g.initializeDefaults("skills",[...oo]);for(const[B,I]of Object.entries(A)){const Q=`skills.${B}`;g.initializeDefaults(Q,I)}}function WD(){const g=IA.getInstance();return g.hasCustomData("skills")||g.getDefaults("skills").length>0}function HD(){WD()||Ro()}class JD{static select(A){ho();const B=IA.getInstance(),I=B.get("races"),Q=B.getWeights("races"),E=B.getMode("races")||"default";return uB.select(I,Q,A,E)}}const UG=class UG{static suggest(A,B){wo();const I=IA.getInstance(),Q=I.get("classes"),E=this.calculateAllAffinities(A,Q),i=this.calculateProbabilities(E),e=I.getWeights("classes"),a=this.applyCustomWeights(i,e,Q),C=Object.entries(a).map(([o,t])=>[o,t]);return B.weightedChoice(C)}static calculateAllAffinities(A,B){const I={};for(const Q of B)I[Q]=this.calculateClassAffinity(A,Q);return I}static calculateClassAffinity(A,B){let I=this.getCustomClassAudioPreferences(B);if(I||(I=Ph[B]),!I)return .5;let Q=0;return Q+=this.getTraitContribution(A,I.primary,I,1),I.secondary&&(Q+=this.getTraitContribution(A,I.secondary,I,.5)),I.tertiary&&(Q+=this.getTraitContribution(A,I.tertiary,I,.25)),Q}static getCustomClassAudioPreferences(A){try{const I=IA.getInstance().get("classes.data");if(I&&Array.isArray(I)){const Q=I.find(E=>E.name===A);if(Q&&Q.audio_preferences)return Q.audio_preferences}}catch{}}static getTraitContribution(A,B,I,Q){switch(B){case"bass":return A.bass_dominance*(I.bass||1)*Q;case"treble":return A.treble_dominance*(I.treble||1)*Q;case"mid":return A.mid_dominance*(I.mid||1)*Q;case"amplitude":return A.average_amplitude*(I.amplitude||1)*Q;case"chaos":{const E=A.bass_dominance,i=A.treble_dominance,e=A.mid_dominance;return(1-(Math.max(E,i,e)-Math.min(E,i,e)))*Q}default:return 0}}static calculateProbabilities(A){const B=Object.keys(A),I=B.length;if(I===0)return{};const Q=Object.values(A).reduce((t,s)=>t+s,0);if(Q===0){const t=1/I,s={};for(const n of B)s[n]=t;return s}const E=this.BASELINE_PROBABILITY*I,i=1-E,e=E>=1?1/I:this.BASELINE_PROBABILITY,a=E>=1?0:i,C={};for(const t of B){const s=A[t]/Q;C[t]=e+s*a}const o=Object.values(C).reduce((t,s)=>t+s,0);for(const t of B)C[t]/=o;return C}static applyCustomWeights(A,B,I){if(Object.keys(B).length===0)return A;const Q=Object.values(B).reduce((a,C)=>a+Math.max(0,C),0);if(Q===0)return A;const E={};for(const[a,C]of Object.entries(B))I.includes(a)&&(E[a]=Math.max(0,C)/Q);const i=1-Object.values(E).reduce((a,C)=>a+C,0),e=Object.entries(A).filter(([a])=>!B[a]).reduce((a,[,C])=>a+C,0);for(const a of I)!B[a]&&A[a]&&(e>0?E[a]=A[a]/e*i:E[a]=i/I.length);return E}};UG.BASELINE_PROBABILITY=.04;let Ji=UG;class xi{static getSpicedValue(A,B,I){let Q;switch(A){case"bass":Q=I.rms_energy??I.dynamic_range??B;break;case"mid":I.spectral_centroid!==void 0?Q=Math.min(1,Math.max(0,(I.spectral_centroid-100)/9900)):Q=I.dynamic_range??B;break;case"treble":I.zero_crossing_rate!==void 0?Q=I.zero_crossing_rate:I.spectral_centroid!==void 0?Q=Math.min(1,Math.max(0,(I.spectral_centroid-100)/9900)):Q=B;break}return(B+Q)/2}static createFrequencyMappings(A){const B=["STR","DEX","CON","INT","WIS","CHA"],I=new Map,Q=A.shuffle(B),E=["bass","mid","treble"];for(let i=0;i<3;i++){const e=E[i],a=Q[i*2],C=Q[i*2+1],o=A.random()<.5;I.set(e,{abilities:[a,C],firstHasSpice:o})}return I}static calculateBaseScores(A,B){const{bass_dominance:I,mid_dominance:Q,treble_dominance:E}=A,i=this.createFrequencyMappings(B),e={STR:8,DEX:8,CON:8,INT:8,WIS:8,CHA:8},a=3.5,C=3.5;for(const[o,t]of i){const[s,n]=t.abilities,r=t.firstHasSpice;let c;switch(o){case"bass":c=I;break;case"mid":c=Q;break;case"treble":c=E;break}const G=r?this.getSpicedValue(o,c,A):c,D=r?c:this.getSpicedValue(o,c,A),h=B.random(),w=B.random();e[s]=Math.floor(8+h*C+G*a),e[n]=Math.floor(8+w*C+D*a)}return e}static applyRacialBonuses(A,B){const I=ri(B);if(!I)return console.warn(`Unknown race: "${B}", using no ability bonuses`),{...A};const Q=I.ability_bonuses,E={...A};if(Q)for(const[i,e]of Object.entries(Q)){const a=i;E[a]=Math.min(20,(E[a]||0)+(e||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 xD{static getSkillListDefinition(A){try{const I=IA.getInstance().get("skillLists");return Array.isArray(I)?I.find(Q=>Q.class===A):void 0}catch{return}}static assignSkills(A,B,I){const Q=CB.getInstance(),E=Q.getAllSkills(),i={};for(const s of E)i[s.id]="none";const e=mC(A);if(!e)return console.warn(`SkillAssigner: Unknown class "${A}", using default skill assignment`),i;const a=this.validateSkills(e.available_skills,Q),C=I?this.filterSkillsByPrerequisites(a,Q,I):a,o=this.getSkillListDefinition(A),t=this.selectSkills(C,e.skill_count,B,o?.selectionWeights);for(const s of t)i[s]="proficient";if(e.has_expertise&&e.expertise_count){const s=this.selectSkills(t,e.expertise_count,B);for(const n of s)i[n]="expertise"}return i}static validateSkills(A,B){const I=[];for(const Q of A)B.isValidSkill(Q)?I.push(Q):console.warn(`SkillAssigner: Invalid skill ID "${Q}" not found in SkillQuery. Skipping.`);return I}static filterSkillsByPrerequisites(A,B,I){const Q=[];for(const E of A){const i=B.getSkill(E);i&&(i.prerequisites&&!LB.validateSkillPrerequisites(i.prerequisites,I).valid||Q.push(E))}return Q}static selectSkills(A,B,I,Q){if(!Q||Q.mode==="default")return this.selectSkillsEqualWeight(A,B,I);const{weights:E,mode:i}=Q,e=[];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 n=0;n<s;n++)e.push(o)}}else{const n=Math.round((t??1)*10);for(let r=0;r<n;r++)e.push(o)}}if(e.length===0)return this.selectSkillsEqualWeight(A,B,I);for(let o=e.length-1;o>0;o--){const t=Math.floor(I.random()*(o+1));[e[o],e[t]]=[e[t],e[o]]}const a=[],C=new Set;for(const o of e)if(!C.has(o)&&(a.push(o),C.add(o),a.length>=B))break;return a}static selectSkillsEqualWeight(A,B,I){const Q=[...A];for(let E=Q.length-1;E>0;E--){const i=Math.floor(I.random()*(E+1));[Q[E],Q[i]]=[Q[i],Q[E]]}return Q.slice(0,B)}}const XZ=["Wizard","Sorcerer","Warlock","Bard","Cleric","Druid","Paladin"];class qD{static generate(A,B,I){so();const Q=new qB(A),E=IA.getInstance(),i=E.get("appearance.bodyTypes"),e=E.getWeights("appearance.bodyTypes"),a=E.getMode("appearance.bodyTypes")||"default",C=E.get("appearance.skinTones"),o=E.getWeights("appearance.skinTones"),t=E.getMode("appearance.skinTones")||"default",s=E.get("appearance.hairStyles"),n=E.getWeights("appearance.hairStyles"),r=E.getMode("appearance.hairStyles")||"default",c=E.get("appearance.hairColors"),G=E.getWeights("appearance.hairColors"),D=E.getMode("appearance.hairColors")||"default",h=E.get("appearance.eyeColors"),w=E.getWeights("appearance.eyeColors"),y=E.getMode("appearance.eyeColors")||"default",R=E.get("appearance.facialFeatures"),Y=E.getWeights("appearance.facialFeatures"),k=E.getMode("appearance.facialFeatures")||"default",W=uB.select(i,e,Q,a),j=uB.select(C,o,Q,t),X=uB.select(s,n,Q,r),z=uB.select(c,G,Q,D),QA=uB.select(h,w,Q,y),CA=Q.randomInt(1,4),dA=uB.selectMultiple(R,Y,Q,CA,k),uA=I.color_palette,AA=uA?.primary_color,EA=uA?.secondary_color,ZA=uA?.accent_color;let NA;return XZ.includes(B)&&(NA=this.generateAuraColor(B,uA?.primary_color)),{body_type:W,skin_tone:j,hair_style:X,hair_color:z,eye_color:QA,facial_features:dA,primary_color:AA,secondary_color:EA,accent_color:ZA,aura_color:NA}}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 I=A.replace("#",""),Q=parseInt(I.substring(0,2),16),E=parseInt(I.substring(2,4),16),i=parseInt(I.substring(4,6),16),e=Math.min(255,Math.floor(Q*B)),a=Math.min(255,Math.floor(E*B)),C=Math.min(255,Math.floor(i*B)),o=t=>t.toString(16).padStart(2,"0");return`#${o(e)}${o(a)}${o(C)}`}}class yo{static isSpellcaster(A){return["Bard","Cleric","Druid","Paladin","Ranger","Sorcerer","Warlock","Wizard"].includes(A)}static getSpellSlots(A,B){if(!this.isSpellcaster(A))return{};const I={};for(let E=0;E<=9;E++)I[E]={total:0,used:0};const Q=pC(A,B);if(!Q)return I;for(const[E,i]of Object.entries(Q)){const e=parseInt(E,10);I[e]={total:i,used:0}}return I}static getCantrips(A){if(!this.isSpellcaster(A))return[];Hi();const B=IA.getInstance(),I=bC(A),Q=I?[...I.cantrips]:[],E=`spells.${A}`,i=B.get(E);for(const e of i){const a=e;if(a.cantrips&&a.cantrips.length>0)for(const C of a.cantrips)Q.includes(C)||Q.push(C)}return Q}static getKnownSpells(A,B,I){if(!this.isSpellcaster(A))return[];Hi();const Q=IA.getInstance(),E=bC(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 e=`spells.${A}`,a=Q.get(e);for(const t of a){const s=t;if(s.cantrips&&s.cantrips.length>0)for(const n of s.cantrips);if(s.spells_by_level)for(const[n,r]of Object.entries(s.spells_by_level)){const c=Number(n);i[c]||(i[c]=[]);for(const G of r)i[c].includes(G)||i[c].push(G)}}const C={spells_by_level:i},o=[];for(let t=1;t<=B&&t<=9;t++){const s=C.spells_by_level[t];s&&s.length>0&&o.push(...s)}return I?this.filterSpellsByPrerequisites(o,I):o}static filterSpellsByPrerequisites(A,B){const I=[];for(const Q of A){const E=yC[Q];if(!E){I.push(Q);continue}E.prerequisites&&!eg.validateSpellPrerequisites(E.prerequisites,B).valid||I.push(Q)}return I}static initializeSpells(A,B,I){return{spell_slots:this.getSpellSlots(A,B),known_spells:this.getKnownSpells(A,B,I),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 I={...A},Q=I[B];return Q&&Q.used<Q.total&&(I[B]={...Q,used:Q.used+1}),I}static restoreSpellSlots(A,B){const I={...A};if(B!==void 0){const Q=I[B];Q&&(I[B]={...Q,used:0})}else for(let Q=1;Q<=9;Q++){const E=I[Q];E&&(I[Q]={...E,used:0})}return I}static filterCharacterSpells(A){if(!A.spells)return A;const B=this.filterSpellsByPrerequisites(A.spells.known_spells||[],A),I=this.filterSpellsByPrerequisites(A.spells.cantrips||[],A);return{...A,spells:{...A.spells,known_spells:B,cantrips:I}}}}const uo={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 LD(g){if(g in uo)return uo[g];try{const A=IA.getInstance(),B=`classStartingEquipment.${g}`,I=A.get(B);if(I&&Array.isArray(I)&&I.length>0){const Q=I[0];return{weapons:Q.weapons,armor:Q.armor,items:Q.items}}}catch{}}function mo(g,A,B){g.ability_scores[A]+=B;const I=g.ability_scores[A];g.ability_modifiers[A]=Math.floor((I-10)/2)}function So(g,A,B){const I=g.skills[A];if(!I||I==="none"){g.skills[A]=B;return}B==="expertise"&&(g.skills[A]=B)}class PA{static equipItem(A,B,I){const Q={applied:!1,count:0,errors:[]};if(A.equipment_effects||(A.equipment_effects=[]),this.findEquipmentEffect(A,B.name,I))return Q.applied=!0,Q;if(B.properties){const e=this.validateRequirements(A,B,B.properties);if(e.length>0)return Q.errors.push(...e),Q}const i={source:B.name,instanceId:I,effects:B.properties?[...B.properties]:[],features:[],skills:[],spells:[]};if(B.properties)for(const e of B.properties)try{this.applyProperty(A,e,B.name),Q.count++}catch(a){const C=a instanceof Error?a.message:String(a);Q.errors.push(`Failed to apply property from ${B.name}: ${C}`)}return B.grantsFeatures&&(this.applyEquipmentFeatures(A,B,I,i.features),Q.count+=i.features.length),B.grantsSkills&&(this.applyEquipmentSkills(A,B,I,i.skills),Q.count+=i.skills.length),B.grantsSpells&&(i.spells=B.grantsSpells.map(e=>({spellId:e.spellId,level:e.level,uses:e.uses,recharge:e.recharge})),this.addSpellsToCharacter(A,B.grantsSpells),Q.count+=i.spells.length),A.equipment_effects.push(i),Q.applied=Q.errors.length===0,Q}static unequipItem(A,B,I){const Q={applied:!1,count:0,errors:[]};if(!A.equipment_effects)return Q.errors.push("No equipment effects found on character"),Q;const E=A.equipment_effects.findIndex(e=>e.source===B&&e.instanceId===I);if(E===-1)return Q.errors.push(`Equipment "${B}" effects not found`),Q;const i=A.equipment_effects[E];return i.effects.length>0&&(this.removeProperties(A,i.effects),Q.count+=i.effects.length),i.features.length>0&&(this.removeEquipmentFeatures(A,B,I),Q.count+=i.features.length),i.skills.length>0&&(this.removeEquipmentSkills(A,i.skills),Q.count+=i.skills.length),i.spells&&i.spells.length>0&&(this.removeSpellsFromCharacter(A,i.spells),Q.count+=i.spells.length),A.equipment_effects.splice(E,1),Q.applied=Q.count>0,Q}static reapplyEquipmentEffects(A){const B={applied:!1,count:0,errors:[]};if(!A.equipment_effects||A.equipment_effects.length===0)return B;const I=[...A.equipment_effects];A.equipment_effects=[];for(const Q of I){const E={source:Q.source,instanceId:Q.instanceId,effects:[...Q.effects],features:[...Q.features],skills:[...Q.skills],spells:Q.spells?[...Q.spells]:[]};for(const i of Q.effects)try{this.applyProperty(A,i,Q.source),B.count++}catch(e){const a=e instanceof Error?e.message:String(e);B.errors.push(`Failed to reapply property from ${Q.source}: ${a}`)}for(const i of Q.features)this.addFeatureToCharacter(A,i),B.count++;for(const i of Q.skills)this.addSkillToCharacter(A,i),B.count++;Q.spells&&(this.addSpellsToCharacter(A,Q.spells),B.count+=Q.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 I of A.equipment_effects)B.push(...I.effects);return B}static evaluateACFormula(A,B){const I=A.trim();if(/^\d+$/.test(I))return parseInt(I,10);const Q=I.match(/^(\d+)\s*\+\s*min\(DEX,\s*(\d+)\)$/i);if(Q){const i=parseInt(Q[1],10),e=parseInt(Q[2],10);return i+Math.min(B,e)}const E=I.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,I){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,I);break;case"damage_bonus":this.trackDamageBonus(A,B,I);break;case"stat_requirement":this.trackStatRequirement(A,B,I);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 I=B.target,Q=B.value;if(bg(I)){mo(A,I,Q);return}}static applySkillProficiency(A,B){const I=B.target.toLowerCase(),Q=B.value;So(A,I,Q)}static applyAbilityUnlock(A,B){}static applyPassiveModifier(A,B){const I=B.target,Q=B.value;if(I==="speed"){A.speed+=Q;return}if(I==="ac"||I==="armor_class"){if(typeof Q=="string"){const E=A.ability_modifiers.DEX??0;A.armor_class=PA.evaluateACFormula(Q,E)}else A.armor_class+=Q;return}if(I==="max_hp"||I==="hp_max"){A.hp.max+=Q,A.hp.current+=Q;return}}static trackSpecialProperty(A,B,I){}static trackDamageBonus(A,B,I){}static removeProperties(A,B){for(let I=B.length-1;I>=0;I--){const Q=B[I];switch(Q.type){case"stat_bonus":this.removeStatBonus(A,Q);break;case"skill_proficiency":this.removeSkillProficiency(A,Q);break;case"passive_modifier":this.removePassiveModifier(A,Q);break}}}static removeStatBonus(A,B){const I=B.target,Q=B.value;bg(I)&&mo(A,I,-Q)}static removeSkillProficiency(A,B){const I=B.target.toLowerCase();A.skills[I]="none"}static removePassiveModifier(A,B){const I=B.target,Q=B.value;I==="speed"?A.speed-=Q:I==="ac"||I==="armor_class"?typeof Q=="string"?A.armor_class=10+(A.ability_modifiers.DEX??0):A.armor_class-=Q:(I==="max_hp"||I==="hp_max")&&(A.hp.max-=Q,A.hp.current=Math.min(A.hp.current,A.hp.max))}static applyEquipmentFeatures(A,B,I,Q){if(B.grantsFeatures)for(const E of B.grantsFeatures)if(typeof E=="string"){const i=KA.getInstance(),e=i.getClassFeatureById(E),a=e?void 0:i.getRacialTraitById(E);if(e||a){const o={featureId:E,source:"equipment",equipmentName:B.name,instanceId:I,sourceType:B.source??"default"};Q.push(o),this.addFeatureToCharacter(A,o)}}else{const i={featureId:E.id,source:"equipment",equipmentName:B.name,instanceId:I,sourceType:B.source??"default"};if(Q.push(i),this.addFeatureToCharacter(A,i),E.effects)for(const e of E.effects)this.applyProperty(A,e,B.name)}}static applyEquipmentSkills(A,B,I,Q){if(B.grantsSkills)for(const E of B.grantsSkills){const i={skillId:E.skillId,level:E.level,source:"equipment",equipmentName:B.name,instanceId:I,sourceType:B.source??"default"};Q.push(i),this.addSkillToCharacter(A,i)}}static addSpellsToCharacter(A,B){A.spells||(A.spells={spell_slots:{},known_spells:[],cantrips:[]});for(const I of B)I.level===0?A.spells.cantrips.includes(I.spellId)||A.spells.cantrips.push(I.spellId):A.spells.known_spells.includes(I.spellId)||A.spells.known_spells.push(I.spellId)}static removeSpellsFromCharacter(A,B){if(A.spells)for(const I of B)if(I.level===0){const Q=A.spells.cantrips.indexOf(I.spellId);Q>-1&&A.spells.cantrips.splice(Q,1)}else{const Q=A.spells.known_spells.indexOf(I.spellId);Q>-1&&A.spells.known_spells.splice(Q,1)}}static addFeatureToCharacter(A,B){A.class_features.includes(B.featureId)||A.class_features.push(B.featureId)}static addSkillToCharacter(A,B){const I=B.skillId.toLowerCase();So(A,I,B.level)}static removeEquipmentFeatures(A,B,I){if(!A.equipment_effects)return;const Q=A.equipment_effects.filter(E=>E.source===B&&E.instanceId===I).flatMap(E=>E.features);for(const E of Q){const i=A.class_features.indexOf(E.featureId);i>-1&&A.class_features.splice(i,1)}}static removeEquipmentSkills(A,B){for(const I of B){const Q=I.skillId.toLowerCase();A.skills[Q]="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,I){if(A.equipment_effects)return A.equipment_effects.find(Q=>Q.source===B&&Q.instanceId===I)}static validateRequirements(A,B,I){const Q=[];for(const E of I)if(E.type==="stat_requirement"){const i=E.target,e=E.value;if(bg(i)){const a=A.ability_scores[i];a<e&&Q.push(`${B.name} requires ${i} ${e}, but character has ${i} ${a}`)}}return Q}static trackStatRequirement(A,B,I){}}class VQ{static ensureInitialized(){co()}static getEquipmentDataStatic(A){return VQ.getEquipmentData(A)}static getEquipmentData(A){return IA.getInstance().get("equipment").find(Q=>Q.name===A)}static getStartingEquipment(A){this.ensureInitialized();const B=LD(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),I=[],Q=[],E=[],i=[...B.weapons,...B.armor,...B.items];for(const a of i){const C=this.getEquipmentData(a);if(C){let o;C.type==="weapon"?o=I:C.type==="armor"?o=Q: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 e=this.getAmmunitionType(A,B.weapons);if(e){const a=this.getAmmunitionQuantity(A),C=E.find(o=>o.name===e);C?C.quantity+=a:E.push({name:e,quantity:a,equipped:!1})}return I.length>0&&(I[0].equipped=!0),Q.length>0&&(Q[0].equipped=!0),{weapons:I,armor:Q,items:E,totalWeight:this.calculateTotalWeight(I,Q,E),equippedWeight:this.calculateEquippedWeight(I,Q,E)}}static addItem(A,B,I=1){this.ensureInitialized();const Q=this.getEquipmentData(B);if(!Q)return A;const E=this.cloneEquipment(A);let i;Q.type==="weapon"?i=E.weapons:Q.type==="armor"?i=E.armor:i=E.items;const e=i.find(a=>a.name===B);return e?I>0&&(e.quantity+=I):i.push({name:B,quantity:Math.max(0,I),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,I=1){if(this.ensureInitialized(),I<=0)return A;const Q=this.cloneEquipment(A);let E;const i=this.getEquipmentData(B);if(!i)return A;i.type==="weapon"?E=Q.weapons:i.type==="armor"?E=Q.armor:E=Q.items;const e=E.findIndex(a=>a.name===B);return e!==-1&&(E[e].quantity>I?E[e].quantity-=I:E.splice(e,1)),Q.totalWeight=this.calculateTotalWeight(Q.weapons,Q.armor,Q.items),Q.equippedWeight=this.calculateEquippedWeight(Q.weapons,Q.armor,Q.items),Q}static equipItem(A,B,I){this.ensureInitialized();const Q=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=Q.weapons:E.type==="armor"?i=Q.armor:i=Q.items;const e=i.find(a=>a.name===B);if(e&&(e.equipped=!0,I)){const a=e.instanceId;PA.equipItem(I,E,a)}return Q.equippedWeight=this.calculateEquippedWeight(Q.weapons,Q.armor,Q.items),Q}static unequipItem(A,B,I){this.ensureInitialized();const Q=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=Q.weapons:E.type==="armor"?i=Q.armor:i=Q.items;const e=i.find(a=>a.name===B);if(e&&(e.equipped=!1,I)){const a=e.instanceId;PA.unequipItem(I,B,a)}return Q.equippedWeight=this.calculateEquippedWeight(Q.weapons,Q.armor,Q.items),Q}static getInventoryList(A){return[...A.weapons,...A.armor,...A.items]}static getEquipmentByType(A,B){return A[B]}static calculateTotalWeight(A,B,I){let Q=0;for(const E of A){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight*E.quantity)}for(const E of B){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight*E.quantity)}for(const E of I){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight*E.quantity)}return Math.round(Q*100)/100}static calculateEquippedWeight(A,B,I){let Q=0;for(const E of A)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight)}for(const E of B)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight)}for(const E of I)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight)}return Math.round(Q*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 I=B.some(e=>e==="Longbow"),Q=B.some(e=>e==="Shortbow"),E=B.some(e=>e==="Light Crossbow"),i=B.some(e=>e==="Hand Crossbow");return I||Q?"Arrow":E||i?"Bolt":null}static getAmmunitionQuantity(A){return{Ranger:20,Fighter:20,Rogue:20}[A]||0}static addModification(A,B,I,Q,E){this.ensureInitialized();const i=this.cloneEquipment(A),e=this.getEquipmentData(B);if(!e)return A;let a;e.type==="weapon"?a=i.weapons:e.type==="armor"?a=i.armor:a=i.items;const C=a.find(t=>t.name===B);if(!C)return A;C.modifications||(C.modifications=[]),!Q&&!C.instanceId&&(C.instanceId=`${B}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`);const o=Q||C.instanceId;return C.modifications.push(I),C.equipped&&E&&(PA.unequipItem(E,B,o),this.applyCombinedEffects(E,e,I,o)),i}static removeModification(A,B,I,Q){this.ensureInitialized();const E=this.cloneEquipment(A),i=this.getEquipmentData(B);if(!i)return A;let e;i.type==="weapon"?e=E.weapons:i.type==="armor"?e=E.armor:e=E.items;const a=e.find(s=>s.name===B);if(!a||!a.modifications)return A;const C=a.equipped,o=a.instanceId,t=a.modifications.findIndex(s=>s.id===I);if(t!==-1&&a.modifications.splice(t,1),C&&Q&&(PA.unequipItem(Q,B,o),PA.equipItem(Q,i,o),a.modifications))for(const s of a.modifications)this.applyCombinedEffects(Q,i,s,o);return E}static getActiveEffects(A,B,I){this.ensureInitialized();const Q=this.getEquipmentData(B);if(!Q)return[];let E;Q.type==="weapon"?E=A.weapons:Q.type==="armor"?E=A.armor:E=A.items;const i=E.find(a=>a.name===B&&(!I||a.instanceId===I));if(!i)return[];const e=Q.properties?[...Q.properties]:[];if(i.modifications)for(const a of i.modifications)a.properties&&e.push(...a.properties);return e}static applyCombinedEffects(A,B,I,Q){const E={...B,properties:[...B.properties||[],...I.properties],grantsFeatures:I.addsFeatures,grantsSkills:I.addsSkills,grantsSpells:I.addsSpells};PA.equipItem(A,E,Q)}}class vQ{static applyFeatureEffects(A,B){const I={applied:!1,count:0,errors:[]};if(!B.effects||B.effects.length===0)return I;for(const Q of B.effects)try{this.applySingleEffect(A,Q,B.id),I.applied=!0,I.count++}catch(E){const i=E instanceof Error?E.message:String(E);I.errors.push(`Failed to apply effect from ${B.id}: ${i}`)}return I}static applyMultipleEffects(A,B){const I={applied:!1,count:0,errors:[]};for(const Q of B){const E=this.applyFeatureEffects(A,Q);I.applied=I.applied||E.applied,I.count+=E.count,I.errors.push(...E.errors)}return I}static applySingleEffect(A,B,I){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 I=B.target,Q=B.value;if(bg(I)){mo(A,I,Q);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 I=B.target.toLowerCase(),Q=B.value;So(A,I,Q)}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 I=B.target,Q=B.value;if(I==="speed"){A.speed+=Q;return}if(I.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 qi{static registerExtensions(A){const B=IA.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:I}=A;I.bodyTypes&&I.bodyTypes.length>0&&B.register("appearance.bodyTypes",I.bodyTypes),I.skinTones&&I.skinTones.length>0&&B.register("appearance.skinTones",I.skinTones),I.hairColors&&I.hairColors.length>0&&B.register("appearance.hairColors",I.hairColors),I.hairStyles&&I.hairStyles.length>0&&B.register("appearance.hairStyles",I.hairStyles),I.eyeColors&&I.eyeColors.length>0&&B.register("appearance.eyeColors",I.eyeColors),I.facialFeatures&&I.facialFeatures.length>0&&B.register("appearance.facialFeatures",I.facialFeatures)}}static generate(A,B,I,Q={}){const E=new qB(A),i=Q.level||1,e=Q.gameMode||"standard";Mo();const a=KA.getInstance();Q.extensions&&qi.registerExtensions(Q.extensions);let C;const o=Q.subrace;let t;if(o==="pure")C=void 0,t=Q.forceRace;else if(o!==void 0)if(Q.forceRace)C=o,t=Q.forceRace;else{const aA=a.getRaceForSubrace(o);if(!aA)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=aA,C=o}const s=t||JD.select(E);if(C!==void 0&&o!=="pure"){const aA=a.getAvailableSubraces(s);if(!aA.includes(C))throw new Error(`Invalid subrace "${C}" for race "${s}". Available subraces: ${aA.length>0?aA.join(", "):"none"}`)}else if(C===void 0&&o===void 0){const SA=["pure",...a.getAvailableSubraces(s)],uI=E.randomChoice(SA);C=uI==="pure"?void 0:uI}const n=Q.forceClass||Ji.suggest(B,E),r=Q.forceName||new SD().generateName(A,I,B,n,Q.deterministicName||!0),c=xi.calculateBaseScores(B,E),G=xi.applyRacialBonuses(c,s),D=xi.calculateModifiers(G),h=mC(n);if(!h)throw new Error(`Unknown class: ${n}. Cannot generate character.`);const y=ri(s)?.speed??30,R=h.hit_die+D.CON,Y=10+D.DEX,k=D.DEX,W=SC[i],j=xD.assignSkills(n,E),X={STR:h.saving_throws.includes("STR"),DEX:h.saving_throws.includes("DEX"),CON:h.saving_throws.includes("CON"),INT:h.saving_throws.includes("INT"),WIS:h.saving_throws.includes("WIS"),CHA:h.saving_throws.includes("CHA")},z=qD.generate(A,n,B),QA=a.getClassFeatures(n,i),CA=C?a.getRacialTraitsForSubrace(s,C):a.getBaseRacialTraits(s),dA=VQ.initializeEquipment(n),uA={name:r,race:s,subrace:C,class:n,level:i,ability_scores:G,ability_modifiers:D,proficiency_bonus:W,hp:{current:R,max:R,temp:0},armor_class:Y,initiative:k,speed:y,skills:j,saving_throws:X,racial_traits:[],class_features:[],appearance:z,spells:{spell_slots:{},known_spells:[],cantrips:[]},equipment:dA,xp:{current:0,next_level:HQ[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:e},AA=yo.initializeSpells(n,i,uA),EA=[];for(const aA of QA){const SA=a.validatePrerequisites(aA,uA);SA.valid||console.warn(`Feature "${aA.name}" (${aA.id}) failed prerequisite validation:`,SA.errors),EA.push(aA)}const ZA=[];for(const aA of CA){const SA=a.validatePrerequisites(aA,uA);SA.valid||console.warn(`Trait "${aA.name}" (${aA.id}) failed prerequisite validation:`,SA.errors),ZA.push(aA)}const NA={name:r,race:s,subrace:C,class:n,level:i,ability_scores:G,ability_modifiers:D,proficiency_bonus:W,hp:{current:R,max:R,temp:0},armor_class:Y,initiative:k,speed:y,skills:j,saving_throws:X,racial_traits:ZA.map(aA=>aA.id),class_features:EA.map(aA=>aA.id),appearance:z,spells:AA,equipment:dA,xp:{current:0,next_level:HQ[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:e};if(vQ.applyMultipleEffects(NA,ZA),vQ.applyMultipleEffects(NA,EA),dA){const aA=[...dA.weapons.filter(SA=>SA.equipped),...dA.armor.filter(SA=>SA.equipped),...dA.items.filter(SA=>SA.equipped)];for(const SA of aA){const uI=VQ.getEquipmentDataStatic(SA.name);if(uI){const kG=SA.instanceId;PA.equipItem(NA,uI,kG).applied||(SA.equipped=!1)}}}return yo.filterCharacterSpells(NA)}}function bo(g){return 2595*Math.log10(1+g/700)}function VD(g){return 700*(Math.pow(10,g/2595)-1)}function XQ(g,A){const B=g.sampleRate,I=B/A,Q=g.length,E=Math.ceil(Q/I),i=new Float32Array(Q);for(let a=0;a<g.numberOfChannels;a++){const C=g.getChannelData(a);for(let o=0;o<Q;o++)i[o]+=C[o]/g.numberOfChannels}const e=new Float32Array(E);for(let a=0;a<E;a++){const C=a*I,o=Math.floor(C),t=Math.min(o+1,Q-1),s=C-o;e[a]=i[o]*(1-s)+i[t]*s}return{data:e,originalSampleRate:B,targetSampleRate:A}}function vD(g,A,B,I=0,Q=B/2){const E=A/2+1,i=[],e=bo(I),a=bo(Q),C=[];for(let t=0;t<g+2;t++)C.push(e+t*(a-e)/(g+1));const o=C.map(t=>{const s=VD(t);return Math.floor((A+1)*s/B)});for(let t=0;t<g;t++){const s=new Float32Array(E),n=o[t],r=o[t+1],c=o[t+2];for(let G=n;G<r;G++)r!==n&&(s[G]=(G-n)/(r-n));for(let G=r;G<c;G++)c!==r&&(s[G]=(c-G)/(c-r));i.push(s)}return i}function XD(g,A,B){if(g.length===0)return new Float32Array(0);const I=1/(2*Math.PI*A),Q=1/B,E=I/(I+Q),i=new Float32Array(g.length);i[0]=g[0];for(let e=1;e<g.length;e++)i[e]=E*(i[e-1]+g[e]-g[e-1]);return i}function po(g,A,B){if(g.length===0)return new Float32Array(0);const I=Math.round(A/1e3*B);if(I<=1)return new Float32Array(g);const Q=I/6,E=I,i=new Float32Array(E),e=Math.floor(E/2);let a=0;for(let o=0;o<E;o++){const t=o-e;i[o]=Math.exp(-(t*t)/(2*Q*Q)),a+=i[o]}for(let o=0;o<E;o++)i[o]/=a;const C=new Float32Array(g.length);for(let o=0;o<g.length;o++){let t=0;for(let s=0;s<E;s++){const n=o+s-e,r=n<0?-n:n>=g.length?2*g.length-n-2:n,c=Math.max(0,Math.min(g.length-1,r));t+=g[c]*i[s]}C[o]=t}return C}function KD(g){if(g.length===0)return 0;let A=0;for(let E=0;E<g.length;E++)A+=g[E];const B=A/g.length;let I=0;for(let E=0;E<g.length;E++){const i=g[E]-B;I+=i*i}const Q=I/g.length;return Math.sqrt(Q)}function zD(g){const A=g.length,B=Math.pow(2,Math.ceil(Math.log2(A))),I=new Float32Array(B),Q=new Float32Array(B);for(let a=0;a<A;a++){const C=.5-.5*Math.cos(2*Math.PI*a/(A-1));I[a]=g[a]*C}let E=0;for(let a=0;a<B-1;a++){a<E&&([I[a],I[E]]=[I[E],I[a]],[Q[a],Q[E]]=[Q[E],Q[a]]);let C=B/2;for(;E>=C;)E-=C,C/=2;E+=C}let i=2;for(;i<=B;){const a=-2*Math.PI/i,C=Math.cos(a),o=Math.sin(a);for(let t=0;t<B;t+=i){let s=1,n=0;for(let r=0;r<i/2;r++){const c=t+r,G=t+r+i/2,D=I[G]*s-Q[G]*n,h=I[G]*n+Q[G]*s;I[G]=I[c]-D,Q[G]=Q[c]-h,I[c]+=D,Q[c]+=h;const w=s*C-n*o;n=s*o+n*C,s=w}}i*=2}const e=new Float32Array(B/2+1);for(let a=0;a<e.length;a++){const C=I[a],o=Q[a];e[a]=Math.sqrt(C*C+o*o)}return e}function Yo(g,A,B,I){const Q=[];let E=0;for(;E+A<=g.length;){const i=g.slice(E,E+A),e=zD(i);Q.push(e),E+=B}return{frames:Q,numFrames:Q.length,fftSize:A,hopSize:B,sampleRate:I}}const TD=[{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 OD(g,A){const B=Math.PI*(2*g-1)/(2*A);return 1/(2*Math.sin(B))}function KZ(g,A,B,I){const Q=2*Math.PI*g/A,E=Math.cos(Q),i=Math.sin(Q),e=OD(B,I),a=i/(2*e),C=1+a,o=(1-E)/2/C,t=(1-E)/C,s=(1-E)/2/C,n=-2*E/C,r=(1-a)/C;return{b0:o,b1:t,b2:s,a1:n,a2:r}}function zZ(g,A,B,I){const Q=2*Math.PI*g/A,E=Math.cos(Q),i=Math.sin(Q),e=OD(B,I),a=i/(2*e),C=1+a,o=(1+E)/2/C,t=-(1+E)/C,s=(1+E)/2/C,n=-2*E/C,r=(1-a)/C;return{b0:o,b1:t,b2:s,a1:n,a2:r}}function jD(g,A){const{b0:B,b1:I,b2:Q,a1:E,a2:i}=A,e=new Float32Array(g.length);e[0]=B*g[0],g.length>1&&(e[1]=B*g[1]+I*g[0]-E*e[0]);for(let a=2;a<g.length;a++)e[a]=B*g[a]+I*g[a-1]+Q*g[a-2]-E*e[a-1]-i*e[a-2];return e}function TZ(g,A,B,I,Q){if(g.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>=I/2)throw new Error(`High frequency (${B} Hz) must be less than Nyquist frequency (${I/2} Hz)`);const i=E/2;let e=new Float32Array(g);for(let a=1;a<=i;a++){const C=zZ(A,I,a,E);e=jD(e,C)}for(let a=1;a<=i;a++){const C=KZ(B,I,a,E);e=jD(e,C)}return e}function OZ(g,A,B,I){const Q=TD.find(E=>E.name===A);if(!Q)throw new Error(`Unknown frequency band: ${A}. Valid bands are: low, mid, high`);return TZ(g,Q.lowHz,Q.highHz,B)}const jZ={targetSampleRate:44100,fftWindowSizeMs:23,hopSizeMs:10,smoothWindowMs:10,peakThreshold:.3,bands:TD};class PD{constructor(A={}){if(this.config={...jZ,...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,I=this.config.targetSampleRate,Q=XQ(A,I),E=Math.pow(2,Math.ceil(Math.log2(this.config.fftWindowSizeMs/1e3*I))),i=Math.round(this.config.hopSizeMs/1e3*I),e=this.config.hopSizeMs/1e3,a=1/e,C=new Map,o=[];for(const r of this.config.bands){const c=this.analyzeBand(Q.data,r,I,E,i,e,a);C.set(r.name,c),o.push(c.energyOverTime)}const t=o[0]?.length??0,s=this.combineEnergyProfiles(o,t),n=this.calculateDominantBands(C);return{bands:C,dominantBands:n,energyProfile:s,metadata:{numFrames:t,duration:B,hopSizeSeconds:e,effectiveSampleRate:I,bandsAnalyzed:this.config.bands.map(r=>r.name)}}}analyzeBand(A,B,I,Q,E,i,e){const a=OZ(A,B.name,I),C=Yo(a,Q,E,I),o=C.numFrames,t=new Float32Array(o);for(let y=0;y<o;y++){const R=C.frames[y];let Y=0;for(let k=0;k<R.length;k++)Y+=R[k]*R[k];t[y]=Math.sqrt(Y/R.length)}const s=Math.max(...t);if(s>0)for(let y=0;y<t.length;y++)t[y]/=s;const n=s,r=this.calculateOnsetEnvelope(C.frames),c=po(r,this.config.smoothWindowMs,e),G=Math.max(...c),D=new Float32Array(c.length);if(G>0)for(let y=0;y<c.length;y++)D[y]=c[y]/G;const h=this.findPeaks(D,this.config.peakThreshold),w=h.map(y=>y*i);return{name:B.name,frequencyRange:{lowHz:B.lowHz,highHz:B.highHz},envelope:D,peaks:h,peakTimes:w,energy:n,energyOverTime:t}}calculateOnsetEnvelope(A){const B=A.length,I=new Float32Array(B);I[0]=0;for(let Q=1;Q<B;Q++){const E=A[Q],i=A[Q-1];let e=0;for(let a=0;a<E.length;a++){const C=E[a]-i[a];C>0&&(e+=C)}I[Q]=e}return I}findPeaks(A,B){const I=[];for(let Q=1;Q<A.length-1;Q++)A[Q]>A[Q-1]&&A[Q]>A[Q+1]&&A[Q]>=B&&I.push(Q);return I}combineEnergyProfiles(A,B){const I=new Float32Array(B);for(let Q=0;Q<B;Q++){let E=0;for(const i of A)Q<i.length&&i[Q]>E&&(E=i[Q]);I[Q]=E}return I}calculateDominantBands(A){const B=[];for(const[I,Q]of A)B.push({name:I,energy:Q.energy});return B.sort((I,Q)=>Q.energy-I.energy),B.map(I=>I.name)}}const Uo={low:{threshold:.5,minInterval:.1,adaptiveThresholding:!1},mid:{threshold:.3,minInterval:.08,adaptiveThresholding:!1},high:{threshold:.25,minInterval:.06,adaptiveThresholding:!1}},PZ={baseThreshold:.3,adaptiveThresholding:!1,adaptiveWindowSize:50,minTransientInterval:.02};class _D{constructor(A={}){const{bands:B,bandConfig:I,...Q}=A,E={low:{...Uo.low,...I?.low},mid:{...Uo.mid,...I?.mid},high:{...Uo.high,...I?.high}};if(this.config={...PZ,...Q,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 e=this.config.bandConfig[i];if(e.threshold<0||e.threshold>1)throw new Error(`${i} band threshold must be between 0 and 1, got: ${e.threshold}`);if(e.minInterval<0)throw new Error(`${i} band minInterval must be non-negative, got: ${e.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,I=[],Q=new Set;for(const[e,a]of A.bands){const C=this.detectBandTransients(e,a,A.metadata.hopSizeSeconds);B.set(e,C),I.push(...C),C.forEach(o=>Q.add(o.detectionMethod))}I.sort((e,a)=>e.timestamp-a.timestamp);const E=new Map;for(const[e,a]of B)E.set(e,a.length);const i=I.length>0?I.reduce((e,a)=>e+a.intensity,0)/I.length:0;return{transients:I,bandTransients:B,metadata:{totalTransients:I.length,transientsPerBand:E,duration:A.metadata.duration,averageIntensity:i,detectionMethodsUsed:Array.from(Q)}}}detectBandTransients(A,B,I){const Q=this.config.bandConfig[A],E=this.getDetectionMethod(A),i=E==="energy"?B.energyOverTime:B.envelope;if(!i||i.length===0)return[];const e=Q.adaptiveThresholding?this.calculateAdaptiveThreshold(i,Q.threshold):Q.threshold,C=this.findPeaks(i,e).map(t=>({timestamp:t*I,intensity:i[t],band:A,detectionMethod:E}));return this.applyNonMaximumSuppression(C,Q.minInterval)}applyNonMaximumSuppression(A,B){if(A.length===0)return[];const I=[...A].sort((E,i)=>i.intensity-E.intensity),Q=[];for(const E of I){let i=!1;for(const e of Q)if(Math.abs(E.timestamp-e.timestamp)<B){i=!0;break}i||Q.push(E)}return Q.sort((E,i)=>E.timestamp-i.timestamp),Q}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 I=B??this.config.baseThreshold;if(A.length===0)return I;let Q=0,E=0;for(let s=0;s<A.length;s++)Q+=A[s],A[s]>E&&(E=A[s]);const i=Q/A.length;let e=0;for(let s=0;s<A.length;s++){const n=A[s]-i;e+=n*n}const a=Math.sqrt(e/A.length),o=1+(i>0?a/i:0)*.5,t=I*o;return Math.max(.1,Math.min(.9,t))}findPeaks(A,B){const I=[];for(let Q=1;Q<A.length-1;Q++)A[Q]>A[Q-1]&&A[Q]>A[Q+1]&&A[Q]>=B&&I.push(Q);return I}}const KQ={densityValidation:{maxRetries:0,baseSensitivityReduction:.1,maxCumulativeReduction:.5},minimumTransientIntensity:0,bands:[]};class fo{constructor(A={}){this.config={densityValidation:{maxRetries:A.densityValidation?.maxRetries??KQ.densityValidation.maxRetries,baseSensitivityReduction:A.densityValidation?.baseSensitivityReduction??KQ.densityValidation.baseSensitivityReduction,maxCumulativeReduction:A.densityValidation?.maxCumulativeReduction??KQ.densityValidation.maxCumulativeReduction},minimumTransientIntensity:A.minimumTransientIntensity??KQ.minimumTransientIntensity,bands:A.bands??KQ.bands}}getConfig(){return{...this.config}}quantize(A,B,I){const Q=this.splitTransientsByBand(A.transients),E=B.quarterNoteInterval/6,i=this.processBand(Q.low,"low",E),e=this.processBand(Q.mid,"mid",E),a=this.processBand(Q.high,"high",E),C={low:this.quantizeBand(i.filteredTransients,B,"low",I),mid:this.quantizeBand(e.filteredTransients,B,"mid",I),high:this.quantizeBand(a.filteredTransients,B,"high",I)},o=i.filteredCount+e.filteredCount+a.filteredCount,t=this.aggregateDensityResults([i.densityResult,e.densityResult,a.densityResult],E);return{streams:C,metadata:{densityValidation:t,transientsFilteredByIntensity:o,transientsFilteredByBand:{low:i.filteredCount,mid:e.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,I){const Q=this.config.densityValidation.maxRetries,E=this.config.densityValidation.baseSensitivityReduction,i=this.config.densityValidation.maxCumulativeReduction;let e=0,a=A;if(this.config.minimumTransientIntensity>0){const n=a.length;a=a.filter(r=>r.intensity>=this.config.minimumTransientIntensity),e=n-a.length}let C=this.config.minimumTransientIntensity,o=0,t=0;for(;t<=Q;){const n=this.validateBandDensity(a,B,I,t,o);if(n.isValid)return{filteredTransients:a,filteredCount:e,densityResult:n};if(t>=Q)return console.warn(`[${B}] Density validation: Max retries (${Q}) reached. Proceeding with ${a.length} transients. Min interval: ${(n.minIntervalDetected*1e3).toFixed(1)}ms (required: ${(I*1e3).toFixed(1)}ms)`),{filteredTransients:a,filteredCount:e,densityResult:n};t++;const r=Math.min(E,i-o);o+=r,C=Math.min(this.config.minimumTransientIntensity+o,1);const c=a.length;a=a.filter(D=>D.intensity>=C);const G=c-a.length;e+=G,console.warn(`[${B}] Density validation retry ${t}: Threshold increased to ${(C*100).toFixed(1)}%, Filtered ${G} transients, ${a.length} remaining`)}const s=this.validateBandDensity(a,B,I,t,o);return{filteredTransients:a,filteredCount:e,densityResult:s}}validateBandDensity(A,B,I,Q,E,i=this.config.minimumTransientIntensity){const e=A.length,a=Math.min(this.config.minimumTransientIntensity+E,1);if(A.length===0)return{band:B,isValid:!0,minIntervalDetected:1/0,requiredMinInterval:I,retryCount:Q,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:e};const C=[...A].sort((s,n)=>s.timestamp-n.timestamp);let o=1/0;for(let s=1;s<C.length;s++){const n=C[s].timestamp-C[s-1].timestamp;n<o&&(o=n)}const t=o>=I;return{band:B,isValid:t,minIntervalDetected:o,requiredMinInterval:I,retryCount:Q,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:e}}aggregateDensityResults(A,B){let I=0,Q=0,E=1/0,i=!0;for(const e of A)e.retryCount>I&&(I=e.retryCount),e.sensitivityReduction>Q&&(Q=e.sensitivityReduction),e.minIntervalDetected<E&&(E=e.minIntervalDetected),e.isValid||(i=!1);return{isValid:i,bands:{low:A.find(e=>e.band==="low"),mid:A.find(e=>e.band==="mid"),high:A.find(e=>e.band==="high")},maxRetryCount:I,maxSensitivityReduction:Q}}decideGrids(A,B,I){const Q=[],E=B.quarterNoteInterval,i=this.getBandGridType(I),e=[...A].sort((a,C)=>a.timestamp-C.timestamp);for(let a=0;a<B.beats.length;a++){const C=B.beats[a],o=C.timestamp,t=a<B.beats.length-1?B.beats[a+1].timestamp:C.timestamp+E,s=e.filter(n=>n.timestamp>=o&&n.timestamp<t);s.length!==0&&(i?Q.push({beatIndex:a,selectedGrid:i,transientCount:s.length,confidence:1}):Q.push(this.detectGrid(s,C,a,E)))}return Q}quantizeToGrids(A,B,I,Q){const E=[],i=B.quarterNoteInterval,e=[...A].sort((C,o)=>C.timestamp-o.timestamp),a=new Map;for(const C of Q)a.set(C.beatIndex,C);for(let C=0;C<B.beats.length;C++){const o=B.beats[C],t=a.get(C);if(!t)continue;const s=o.timestamp,n=C<B.beats.length-1?B.beats[C+1].timestamp:o.timestamp+i,r=e.filter(c=>c.timestamp>=s&&c.timestamp<n);for(const c of r){const G=this.quantizeTransient(c,o,C,t.selectedGrid,i);G&&E.push(G)}}return E}quantizeBand(A,B,I,Q){const E=Q?Q(A,B,I):this.decideGrids(A,B,I),i=this.quantizeToGrids(A,B,I,E),e=this.deduplicateBeats(i);return{audioId:B.audioId,duration:B.duration,beats:e,gridDecisions:E,quarterNoteInterval:B.quarterNoteInterval}}deduplicateBeats(A){const B=new Map;for(const I of A){const Q=`${I.beatIndex}:${I.gridPosition}:${I.gridType}`,E=B.get(Q);(!E||I.intensity>E.intensity)&&B.set(Q,I)}return Array.from(B.values()).sort((I,Q)=>I.timestamp-Q.timestamp)}getBandGridType(A){switch(A){case"low":return"straight_8th";case"mid":case"high":return null}}detectGrid(A,B,I,Q){const E=this.calculateStraightGrid(B.timestamp,Q),i=this.calculateTripletGrid(B.timestamp,Q);let e=0,a=0,C=0;for(const r of A){const c=this.calculateOffsetFromGrid(r,E),G=this.calculateOffsetFromGrid(r,i);e+=c,a+=G,C++}const o=C>0?e/C:0,t=C>0?a/C:0,s=o<=t?"straight_16th":"triplet_8th",n=Math.abs(o-t);return{beatIndex:I,selectedGrid:s,straightAvgOffset:o,tripletAvgOffset:t,transientCount:C,confidence:n}}calculateStraightGrid(A,B){const I=[],Q=B/4;for(let E=0;E<4;E++)I.push(A+E*Q);return I}calculateTripletGrid(A,B){const I=[],Q=B/3;for(let E=0;E<3;E++)I.push(A+E*Q);return I}calculate8thGrid(A,B){const I=[],Q=B/2;for(let E=0;E<2;E++)I.push(A+E*Q);return I}calculateOffsetFromGrid(A,B){let I=1/0;for(const Q of B){const E=Math.abs(A.timestamp-Q);E<I&&(I=E)}return I*1e3}quantizeTransient(A,B,I,Q,E){let i,e;switch(Q){case"straight_8th":i=1,e=E/2;break;case"straight_16th":i=3,e=E/4;break;case"triplet_8th":i=2,e=E/3;break}const a=Math.round((A.timestamp-B.timestamp)/e);if(a<0||a>i)return null;const C=B.timestamp+a*e,o=Math.abs(A.timestamp-C)*1e3;return{timestamp:C,detectedTimestamp:A.timestamp,beatIndex:I,gridPosition:a,gridType:Q,intensity:A.intensity,band:A.band,quantizationError:o}}}class $D{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:I}=B,Q=I>=this.restrictTripletBpm;return A.map(E=>{const{selectedGrid:i}=E;return i==="straight_8th"?E:i==="straight_16th"&&I>=this.restrict16thBpm?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:i==="triplet_8th"&&Q?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:E})}}const ko={rules:[new $D],enabled:!0};class Ad{constructor(A=ko,B){this.config=A,this.rhythmQuantizer=B??new fo}getConfig(){return{...this.config}}decideGrids(A,B,I){const Q=this.rhythmQuantizer.decideGrids(A,B,I),E={bpm:B.quarterNoteBpm,quarterNoteInterval:B.quarterNoteInterval,band:I,transients:A};return this.applyRules(Q,E)}applyRules(A,B){if(this.config.enabled===!1)return A;let I=A;for(const Q of this.config.rules)Q.applies(B.bpm,B)&&(I=Q.apply(I,B));return I}}const _Z={phraseSizes:[1,2,4,8],minOccurrences:3,topSignificantCount:10,includePhrasesWithoutVariation:!1,minNotesPerPhrase:g=>1+g};class Bd{constructor(A={}){this.config={..._Z,...A}}analyze(A){const B={low:this.analyzeBand(A.low,"low"),mid:this.analyzeBand(A.mid,"mid"),high:this.analyzeBand(A.high,"high")},I=[...B.low.phrases,...B.mid.phrases,...B.high.phrases],Q=new Map;Q.set("low",B.low.phrases),Q.set("mid",B.mid.phrases),Q.set("high",B.high.phrases);const E=new Map;for(const C of this.config.phraseSizes){const o=I.filter(t=>t.sizeInBeats===C);o.length>0&&E.set(C,o)}const e=[...I].sort((C,o)=>o.significance-C.significance).slice(0,this.config.topSignificantCount),a=I.filter(C=>C.hasVariation&&C.availableForReuse);return{phrases:I,phrasesByBand:Q,mostSignificantPhrases:e,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 I=Math.max(...A.beats.map(a=>a.beatIndex),0),Q=new Map;for(const a of this.config.phraseSizes)for(let C=0;C<=I-a+1;C++){const o=this.extractPhraseCandidate(A,C,a,B);if(o){const t=Q.get(o.hash);t?t.push(o):Q.set(o.hash,[o])}}const E=[];for(const[a,C]of Q){if(C.length<this.config.minOccurrences)continue;const o=C[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=C.map(c=>({beatIndex:c.startBeatIndex,startTimestamp:c.startTimestamp,endTimestamp:c.endTimestamp})),n=this.calculateSignificance(o.sizeInBeats,C.length),r=t&&C.length>=this.config.minOccurrences;E.push({id:a,pattern:o.pattern,sizeInBeats:o.sizeInBeats,sourceBand:B,occurrences:s,significance:n,hasVariation:t,availableForReuse:r})}E.sort((a,C)=>C.significance-a.significance);const i=new Map;for(const a of this.config.phraseSizes){const C=E.filter(o=>o.sizeInBeats===a);C.length>0&&i.set(a,C)}const e=E.filter(a=>a.hasVariation);return{band:B,phrases:E,phrasesBySize:i,phrasesWithVariation:e}}extractPhraseCandidate(A,B,I,Q){const E=B+I-1,i=A.beats.filter(t=>t.beatIndex>=B&&t.beatIndex<=E);if(i.length===0)return null;const e=i.map(t=>({...t,beatIndex:t.beatIndex-B})),a=this.hashPattern(e,I),C=Math.min(...i.map(t=>t.timestamp)),o=Math.max(...i.map(t=>t.timestamp));return{hash:a,pattern:e,sizeInBeats:I,startBeatIndex:B,startTimestamp:C,endTimestamp:o}}hashPattern(A,B){const Q=[...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}_${Q.join("|")}`}hasPatternVariation(A,B){if(A.length===0)return!1;if(A.some(e=>e.gridType==="triplet_8th")||A.some(e=>e.gridPosition===1||e.gridPosition===3))return!0;const I=A.map(e=>e.intensity),Q=Math.max(...I),E=Math.min(...I);if(Q-E>.1)return!0;if(A.length===B&&A.every(a=>a.gridPosition===0))return!1;const i=new Set(A.map(e=>e.gridPosition));return!(i.size===2&&i.has(0)&&i.has(2)&&this.countBeatsWithNoteCount(A,2)===B)}countBeatsWithNoteCount(A,B){const I=new Map;for(const E of A){const i=I.get(E.beatIndex)??0;I.set(E.beatIndex,i+1)}let Q=0;for(const E of I.values())E===B&&Q++;return Q}calculateSignificance(A,B){const I=A,Q=Math.log2(B+1);return I*Q}}const $Z={beatsPerSection:8,sparseThreshold:1,denseThreshold:1.5};class gd{constructor(A={}){this.config={...$Z,...A}}analyze(A,B,I){const Q=B/60,E={low:this.analyzeBand(A.streams.low,"low",Q,I),mid:this.analyzeBand(A.streams.mid,"mid",Q,I),high:this.analyzeBand(A.streams.high,"high",Q,I)};[...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),e=this.calculateCombinedMetrics(i,Q,I),a=this.calculateSectionMetrics(i,Q,I);return{bandMetrics:E,combinedMetrics:e,sections:a,perBeatDensity:i}}analyzeBand(A,B,I,Q){const E=A.beats,e=(E.length>0?Math.max(...E.map(h=>h.beatIndex)):0)+1,a=new Map;for(const h of E){const w=a.get(h.beatIndex);w?(w.count++,w.intensities.push(h.intensity)):a.set(h.beatIndex,{count:1,intensities:[h.intensity]})}const C=[];let o=0;for(let h=0;h<e;h++){const w=a.get(h),y=w?.count??0,R=w?w.intensities.reduce((Y,k)=>Y+k,0)/w.intensities.length:0;C.push({beatIndex:h,transientCount:y,bands:y>0?[B]:[],averageIntensity:R}),o+=y}const t=C.map(h=>h.transientCount);let s;Q&&Q>0?s=o/Q:s=e>0?o/e*I:0;const n=t.length>0?Math.min(...t)*I:0,r=t.length>0?Math.max(...t)*I:0,c=this.calculateVariance(t,s/I)*I*I,G=this.categorizeDensity(s),D=this.determineNaturalDifficulty(G);return{band:B,totalBeats:e,totalTransients:o,notesPerSecond:s,minNotesPerSecond:n,maxNotesPerSecond:r,variance:c,densityCategory:G,naturalDifficulty:D,perBeatDensity:C}}calculateCombinedPerBeatDensity(A,B,I){const Q=[...A.beats,...B.beats,...I.beats],i=(Q.length>0?Math.max(...Q.map(C=>C.beatIndex)):0)+1,e=new Map;for(const C of A.beats)this.addToBeatData(e,C,"low");for(const C of B.beats)this.addToBeatData(e,C,"mid");for(const C of I.beats)this.addToBeatData(e,C,"high");const a=[];for(let C=0;C<i;C++){const o=e.get(C);if(o){const t=o.intensities.length>0?o.intensities.reduce((s,n)=>s+n,0)/o.intensities.length:0;a.push({beatIndex:C,transientCount:o.count,bands:Array.from(o.bands),averageIntensity:t})}else a.push({beatIndex:C,transientCount:0,bands:[],averageIntensity:0})}return a}addToBeatData(A,B,I){const Q=A.get(B.beatIndex);if(Q)Q.count++,Q.bands.add(I),Q.intensities.push(B.intensity);else{const E=new Set;E.add(I),A.set(B.beatIndex,{count:1,bands:E,intensities:[B.intensity]})}}calculateCombinedMetrics(A,B,I){const Q=A.reduce((a,C)=>a+C.transientCount,0);let E;if(I&&I>0)E=Q/I;else{const a=A.length;E=a>0?Q/a*B:0}const i=this.categorizeDensity(E),e=this.determineNaturalDifficulty(i);return{totalTransients:Q,notesPerSecond:E,densityCategory:i,naturalDifficulty:e}}calculateSectionMetrics(A,B,I){const Q=[],E=this.config.beatsPerSection,i=A.length;for(let e=0;e<i;e+=E){const a=Math.min(e+E-1,i-1),C=A.slice(e,a+1),o=C.reduce((h,w)=>h+w.transientCount,0),t=C.length,s=t>0?o/t*B:0,n=C.map(h=>h.transientCount),r=n.length>0?Math.min(...n)*B:0,c=n.length>0?Math.max(...n)*B:0,G=this.categorizeDensity(s),D=this.determineNaturalDifficulty(G);Q.push({startBeat:e,endBeat:a,beatCount:t,totalTransients:o,notesPerSecond:s,minNotesPerSecond:r,maxNotesPerSecond:c,densityCategory:G,naturalDifficulty:D})}return Q}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(Q=>Math.pow(Q-B,2)).reduce((Q,E)=>Q+E,0)/A.length}getConfig(){return{...this.config}}}const Id={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}},AN={low:.8,mid:.95,high:1},BN={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 gN(g){const A=BN[g];return{...Id,...A,bandBiasWeights:{...AN}}}class Qd{constructor(A={}){this.config={...Id,...A}}score(A,B,I){const Q=[],E={low:[],mid:[],high:[]},i=[...A.streams.low.beats,...A.streams.mid.beats,...A.streams.high.beats],e=i.length>0?Math.max(...i.map(n=>n.beatIndex)):0,a=e+1,C=["low","mid","high"];for(let n=0;n<a;n+=this.config.beatsPerSection){const r=Math.min(n+this.config.beatsPerSection-1,e),c={start:n,end:r};for(const G of C){const D=this.scoreSection(A.streams[G],G,c,B,I);Q.push(D),E[G].push(D.score)}}const o={low:E.low.reduce((n,r)=>n+r,0),mid:E.mid.reduce((n,r)=>n+r,0),high:E.high.reduce((n,r)=>n+r,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(Q);return{sectionScores:Q,bandTotals:o,bandAverages:t,sectionWinners:s,config:{...this.config}}}scoreSection(A,B,I,Q,E){const i=A.beats.filter(s=>s.beatIndex>=I.start&&s.beatIndex<=I.end),e=this.calculateIOIVariance(i),a=this.calculateSyncopationLevel(i),C=this.calculatePhraseSignificance(Q,B,I),o=this.calculateDensityFactor(E,B,I);let t=e*this.config.ioiVarianceWeight+a*this.config.syncopationWeight+C*this.config.phraseSignificanceWeight+o*this.config.densityWeight;if(this.config.bandBiasWeights){const s=this.config.bandBiasWeights[B]??1;t*=s}return{beatRange:I,band:B,score:t,factors:{ioiVariance:e,syncopationLevel:a,phraseSignificance:C,densityFactor:o}}}calculateIOIVariance(A){if(A.length<2)return 0;const B=[...A].sort((a,C)=>a.timestamp-C.timestamp),I=[];for(let a=1;a<B.length;a++)I.push(B[a].timestamp-B[a-1].timestamp);if(I.length===0)return 0;const Q=I.reduce((a,C)=>a+C,0)/I.length,E=I.reduce((a,C)=>a+Math.pow(C-Q,2),0)/I.length,i=Math.sqrt(E),e=Q>0?i/Q:0;return Math.min(e,1)}calculateSyncopationLevel(A){if(A.length===0)return 0;let B=0,I=0;for(const Q of A){const i=this.config.offbeatGridPositions[Q.gridType].includes(Q.gridPosition),e=Q.intensity;i&&(B+=e),I+=e}return I===0?0:B/I}calculatePhraseSignificance(A,B,I){const Q=A.phrasesByBand.get(B)??[];if(Q.length===0)return 0;let E=0,i=0;for(const a of Q){i=Math.max(i,a.significance);for(const C of a.occurrences){const o=C.beatIndex+a.sizeInBeats-1;if(C.beatIndex<=I.end&&o>=I.start){const t=Math.max(C.beatIndex,I.start),r=(Math.min(o,I.end)-t+1)/a.sizeInBeats;E+=a.significance*r;break}}}if(i===0)return 0;const e=E/i;return Math.min(e,1)}calculateDensityFactor(A,B,I){const i=A.bandMetrics[B].perBeatDensity.filter(n=>n.beatIndex>=I.start&&n.beatIndex<=I.end);if(i.length===0)return 0;const e=i.reduce((n,r)=>n+r.transientCount,0)/i.length,a=this.config.bpm!=null?this.config.bpm/60:1,C=e*a;return Math.exp(-Math.pow(C-1,2)/(2*Math.pow(.75,2)))}determineSectionWinners(A){const B=new Map;for(const Q of A){const E=`${Q.beatRange.start}-${Q.beatRange.end}`,i=B.get(E);i?i.push(Q):B.set(E,[Q])}const I=[];for(const[,Q]of B){if(Q.length===0)continue;const E=[...Q].sort((C,o)=>o.score-C.score),i=E[0],e=E[1],a=e?i.score-e.score:i.score;I.push({beatRange:i.beatRange,winner:i.band,score:i.score,margin:a})}return I.sort((Q,E)=>Q.beatRange.start-E.beatRange.start),I}getConfig(){return{...this.config}}updateConfig(A){this.config={...this.config,...A}}}const IN={transitionOverlapBeats:0,preserveGridDecisions:!0},QN=1,EN=1.5;class Ed{constructor(A={}){this.config={...IN,...A}}generate(A,B,I,Q){const E=B.sectionWinners,i={low:0,mid:0,high:0},e={low:0,mid:0,high:0},C=E.filter(D=>{const h=["low","mid","high"];let w=!1;for(const y of h)if(A.streams[y].beats.filter(k=>k.beatIndex>=D.beatRange.start&&k.beatIndex<=D.beatRange.end).length>0){w=!0;break}return w}).map(D=>({beatRange:D.beatRange,sourceBand:D.winner,score:D.score,margin:D.margin}));for(const D of C)e[D.sourceBand]++;const o=[];for(const D of C){const h=A.streams[D.sourceBand],w=this.extractSectionBeats(h,D.beatRange,D.sourceBand);o.push(...w),i[D.sourceBand]+=w.length}o.sort((D,h)=>D.timestamp-h.timestamp);const t=this.deduplicateBeats(o),s=A.streams.low.quarterNoteInterval,n=60/s,r=this.determineNaturalDifficulty(t,I,n,Q),c=C.length,G={totalBeats:t.length,sectionCount:c,beatsPerBand:i,sectionsPerBand:{low:c>0?e.low/c:0,mid:c>0?e.mid/c:0,high:c>0?e.high/c:0}};return{beats:t,sections:C,naturalDifficulty:r,quarterNoteInterval:s,metadata:G}}extractSectionBeats(A,B,I){return A.beats.filter(Q=>Q.beatIndex>=B.start&&Q.beatIndex<=B.end).map(Q=>({...Q,sourceBand:I}))}deduplicateBeats(A){const B=new Map;for(const I of A){const Q=Math.round(I.timestamp*1e3),E=B.get(Q);(!E||I.intensity>E.intensity)&&B.set(Q,I)}return Array.from(B.values()).sort((I,Q)=>I.timestamp-Q.timestamp)}determineNaturalDifficulty(A,B,I,Q){if(A.length===0)return"easy";let E;if(Q&&Q>0)E=A.length/Q;else{const e=Math.max(...A.map(a=>a.beatIndex))+1;E=A.length/e*(I/60)}return E<QN?"easy":E>EN?"hard":"medium"}getConfig(){return{...this.config}}}const Li={strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},iN={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 eN(g){return{...iN[g]}}function id(g){return g%3===0?3:2}function ed(g,A){return g%A===0}function ad(g,A){return g%A!==0}function Cd(g,A){let B=g[0];for(const I of g)if(I.startBeat<=A)B=I;else break;return B}function od(g,A,B){if(B==="neutral")return!1;const I=id(A);return B==="natural"?ed(g,I):ad(g,I)}class td{constructor(A={}){this.config={...Li,...A}}getConfig(){return{...this.config}}balance(A,B){const I={shiftedToDownbeat:0,emptyMeasuresFilled:0,proximityShifts:0,beatsAdded:0,beatsShifted:0,marginRemovals:0};let Q=[...A.beats];return Q=this.shiftLoneSubdivisionNotes(Q,B,I),Q=this.fillEmptyMeasures(Q,B,I),Q=this.enforceDownbeatProximity(Q,B,I),Q=this.removeMarginNotes(Q,B.duration,I),Q.sort((E,i)=>E.timestamp-i.timestamp),{composite:{...A,beats:Q,metadata:{...A.metadata,totalBeats:Q.length}},stats:I}}shiftLoneSubdivisionNotes(A,B,I){if(!B.downbeatConfig?.segments)return A;const Q=new Map;for(const i of A){const e=B.beats[i.beatIndex];if(e){const a=e.measureNumber;Q.has(a)||Q.set(a,[]),Q.get(a).push(i)}}const E=[];for(const i of A){const e=B.beats[i.beatIndex];if(!e){E.push(i);continue}const a=e.measureNumber;if((Q.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),I.shiftedToDownbeat++,I.beatsShifted++}else E.push(i)}return E}fillEmptyMeasures(A,B,I){if(!this.config.fillEmptyMeasures||!B.downbeatConfig?.segments)return A;let Q=1/0,E=-1/0;for(const C of B.beats)Q=Math.min(Q,C.measureNumber),E=Math.max(E,C.measureNumber);if(Q===1/0)return A;const i=new Map;for(const C of A){const o=B.beats[C.beatIndex];if(o){const t=o.measureNumber;i.has(t)||i.set(t,[]),i.get(t).push(C)}}const e=new Map;for(const C of A)e.set(C.beatIndex,C.gridType);const a=[];for(let C=Q;C<=E;C++)if((i.get(C)||[]).length===0){const t=B.beats.findIndex(s=>s.measureNumber===C&&s.isDownbeat);if(t>=0){let s="straight_8th";for(let c=1;c<=8;c++){const G=t-c,D=t+c;if(e.has(G)){s=e.get(G);break}if(e.has(D)){s=e.get(D);break}}const r={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(r),I.emptyMeasuresFilled++,I.beatsAdded++}}return[...A,...a]}enforceDownbeatProximity(A,B,I){const Q=this.config.downbeatProximityRange;if(Q<0)return A;const E=new Set;for(const e of A)e.gridPosition===0&&E.add(e.beatIndex);const i=[];for(const e of A){if(e.gridPosition===0){i.push(e);continue}let a=!1;const C=Math.ceil(Q);for(let o=0;o<=C&&!(o>Q);o++)if(o===0){if(E.has(e.beatIndex)){a=!0;break}}else if(E.has(e.beatIndex-o)||E.has(e.beatIndex+o)){a=!0;break}if(a)i.push(e);else{const o={...e,gridPosition:0,timestamp:B.beats[e.beatIndex]?.timestamp??e.timestamp,balancerAction:"proximity_shift"};i.push(o),E.add(e.beatIndex),I.proximityShifts++,I.beatsShifted++}}return i}removeMarginNotes(A,B,I){const Q=this.config.marginSeconds;if(Q<=0||B<=0)return A;const E=B-Q;return A.filter(i=>i.timestamp<Q||i.timestamp>E?(I.marginRemovals++,!1):!0)}}const aN=["straight_16th","triplet_8th","straight_8th","quarter_triplet","straight_4th"],Zo={straight_16th:4,straight_8th:2,triplet_8th:3,straight_4th:1,quarter_triplet:1},vB={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}}},sd=70,nd=70,rd=120;function ng(g,A){if(g==="natural")return[...vB.natural.allowedGridTypes];if(g==="easy")return["straight_4th","quarter_triplet"];if(g==="medium")return["straight_8th","quarter_triplet"];if(g==="hard")return A>=nd?["straight_8th","quarter_triplet"]:[...vB.hard.allowedGridTypes];if(g==="custom")return[...vB.custom.allowedGridTypes];const B=g;throw new Error(`Unhandled difficulty: ${B}`)}const CN={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 cd(g,A){const B=CN[g.maxGridType]??[g.maxGridType];if(!g.bpmBasedQuantization)return[...B];const I=g.restrictBpm??sd,Q=g.quarterNoteBpm??rd;let E=[...B];return A>=I&&(E=E.filter(i=>i!=="straight_16th"&&i!=="triplet_8th")),A>Q&&(E=E.filter(i=>i!=="straight_8th")),E}function Gd(g,A){if(g.length===0||A<=0)return 0;const B=60/A;return Math.max(...g.map(Q=>Zo[Q]))/B}const oN={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 tN(g,A,B){return B!==void 0?ng(A,B).includes(g):vB[A].allowedGridTypes.includes(g)}function sN(g,A){return A!==void 0?ng(g,A):[...vB[g].allowedGridTypes]}function Vi(g,A,B,I){const Q=I??(B!==void 0?ng(A,B):vB[A].allowedGridTypes);if(Q.includes(g))return g;switch(g){case"straight_16th":return Q.includes("straight_4th")&&!Q.includes("straight_8th")?"straight_4th":"straight_8th";case"triplet_8th":return"quarter_triplet";case"straight_8th":return"straight_4th";default:return g}}function nN(g){return g}function hd(g,A,B){const I=[],Q=B!==void 0?ng(A,B):vB[A].allowedGridTypes;for(const E of g)Q.includes(E.gridType)||I.push({beat:E,gridType:E.gridType,suggestedConversion:Vi(E.gridType,A,B)});return{isValid:I.length===0,violations:I,totalBeats:g.length,violationCount:I.length}}class vi{constructor(A={}){this.currentUnifiedBeatMap=null,this.config={...oN,...A}}lockGridPerBeatIndex(A,B,I,Q,E){const i=this.enforceSingleGridPerBeat(A),e=new Map;if(i.length===0)return{beats:[],gridLock:e};const a=Math.max(...i.map(t=>t.beatIndex)),C=new Map;for(const t of i){const s=C.get(t.beatIndex)??[];s.push(t),C.set(t.beatIndex,s)}for(const[t,s]of C)e.set(t,s[0].gridType);const o=E??ng(B,I);for(let t=0;t<=a;t++){if(e.has(t))continue;if(Q?.has(t)){const r=Q.get(t);e.set(t,r.selectedGrid);continue}let s=!1;for(const r of[1,-1,2,-2,3,-3]){const c=t+r;if(e.has(c)){e.set(t,e.get(c)),s=!0;break}}if(s)continue;const n=o[0]??"straight_8th";e.set(t,n)}return{beats:i,gridLock:e}}generate(A,B,I,Q){this.currentUnifiedBeatMap=B;const E=A.naturalDifficulty,i=this.generateVariant(A,"easy",E,B,I,Q),e=this.generateVariant(A,"medium",E,B,I,Q),a=this.generateVariant(A,"hard",E,B,I,Q);this.validateGridLockResult(i.beats,"easy"),this.validateGridLockResult(e.beats,"medium"),this.validateGridLockResult(a.beats,"hard");const C={difficulty:"natural",beats:this.enforceSingleGridPerBeat([...A.beats]),isUnedited:!0,editType:"none",editAmount:0};this.validateVariant(i,"easy"),this.validateVariant(e,"medium"),this.validateVariant(a,"hard");const o=B?.duration??120;if(i.densityValidation=this.validateDensityInRange(i,o),e.densityValidation=this.validateDensityInRange(e,o),a.densityValidation=this.validateDensityInRange(a,o),this.config.logConversions){const t=s=>{const n=s.densityValidation,r=n.targetRange.max===1/0?"∞":n.targetRange.max.toFixed(1),c=n.inRange?"✓":"✗";return`${s.difficulty}: ${n.density.toFixed(2)} nps (target [${n.targetRange.min}, ${r}]) ${c}`};console.log(`[DifficultyVariantGenerator] Density validation summary:
|
|
49
|
+
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const i of g.seen.entries()){const e=i[1];if(A===i[0]){E(i);continue}if(g.external){const C=g.external.registry.get(i[0])?.id;if(A!==i[0]&&C){E(i);continue}}if(g.metadataRegistry.get(i[0])?.id){E(i);continue}if(e.cycle){E(i);continue}if(e.count>1&&g.reused==="ref"){E(i);continue}}}function AD(g,A){const B=g.seen.get(A);if(!B)throw new Error("Unprocessed schema. This is a bug in Zod.");const I=i=>{const e=g.seen.get(i);if(e.ref===null)return;const a=e.def??e.schema,C={...a},o=e.ref;if(e.ref=null,o){I(o);const s=g.seen.get(o),n=s.schema;if(n.$ref&&(g.target==="draft-07"||g.target==="draft-04"||g.target==="openapi-3.0")?(a.allOf=a.allOf??[],a.allOf.push(n)):Object.assign(a,n),Object.assign(a,C),i._zod.parent===o)for(const c in a)c==="$ref"||c==="allOf"||c in C||delete a[c];if(n.$ref&&s.def)for(const c in a)c==="$ref"||c==="allOf"||c in s.def&&JSON.stringify(a[c])===JSON.stringify(s.def[c])&&delete a[c]}const t=i._zod.parent;if(t&&t!==o){I(t);const s=g.seen.get(t);if(s?.schema.$ref&&(a.$ref=s.schema.$ref,s.def))for(const n in a)n==="$ref"||n==="allOf"||n in s.def&&JSON.stringify(a[n])===JSON.stringify(s.def[n])&&delete a[n]}g.override({zodSchema:i,jsonSchema:a,path:e.path??[]})};for(const i of[...g.seen.entries()].reverse())I(i[0]);const Q={};if(g.target==="draft-2020-12"?Q.$schema="https://json-schema.org/draft/2020-12/schema":g.target==="draft-07"?Q.$schema="http://json-schema.org/draft-07/schema#":g.target==="draft-04"?Q.$schema="http://json-schema.org/draft-04/schema#":g.target,g.external?.uri){const i=g.external.registry.get(A)?.id;if(!i)throw new Error("Schema is missing an `id` property");Q.$id=g.external.uri(i)}Object.assign(Q,B.def??B.schema);const E=g.external?.defs??{};for(const i of g.seen.entries()){const e=i[1];e.def&&e.defId&&(E[e.defId]=e.def)}g.external||Object.keys(E).length>0&&(g.target==="draft-2020-12"?Q.$defs=E:Q.definitions=E);try{const i=JSON.parse(JSON.stringify(Q));return Object.defineProperty(i,"~standard",{value:{...A["~standard"],jsonSchema:{input:pi(A,"input",g.processors),output:pi(A,"output",g.processors)}},enumerable:!1,writable:!1}),i}catch{throw new Error("Error converting schema to JSON.")}}function EB(g,A){const B=A??{seen:new Set};if(B.seen.has(g))return!1;B.seen.add(g);const I=g._zod.def;if(I.type==="transform")return!0;if(I.type==="array")return EB(I.element,B);if(I.type==="set")return EB(I.valueType,B);if(I.type==="lazy")return EB(I.getter(),B);if(I.type==="promise"||I.type==="optional"||I.type==="nonoptional"||I.type==="nullable"||I.type==="readonly"||I.type==="default"||I.type==="prefault")return EB(I.innerType,B);if(I.type==="intersection")return EB(I.left,B)||EB(I.right,B);if(I.type==="record"||I.type==="map")return EB(I.keyType,B)||EB(I.valueType,B);if(I.type==="pipe")return EB(I.in,B)||EB(I.out,B);if(I.type==="object"){for(const Q in I.shape)if(EB(I.shape[Q],B))return!0;return!1}if(I.type==="union"){for(const Q of I.options)if(EB(Q,B))return!0;return!1}if(I.type==="tuple"){for(const Q of I.items)if(EB(Q,B))return!0;return!!(I.rest&&EB(I.rest,B))}return!1}const tf=(g,A={})=>B=>{const I=_l({...B,processors:A});return HA(g,I),$l(I,g),AD(I,g)},pi=(g,A,B={})=>I=>{const{libraryOptions:Q,target:E}=I??{},i=_l({...Q??{},target:E,io:A,processors:B});return HA(g,i),$l(i,g),AD(i,g)},sf={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},nf=(g,A,B,I)=>{const Q=B;Q.type="string";const{minimum:E,maximum:i,format:e,patterns:a,contentEncoding:C}=g._zod.bag;if(typeof E=="number"&&(Q.minLength=E),typeof i=="number"&&(Q.maxLength=i),e&&(Q.format=sf[e]??e,Q.format===""&&delete Q.format,e==="time"&&delete Q.format),C&&(Q.contentEncoding=C),a&&a.size>0){const o=[...a];o.length===1?Q.pattern=o[0].source:o.length>1&&(Q.allOf=[...o.map(t=>({...A.target==="draft-07"||A.target==="draft-04"||A.target==="openapi-3.0"?{type:"string"}:{},pattern:t.source}))])}},rf=(g,A,B,I)=>{const Q=B,{minimum:E,maximum:i,format:e,multipleOf:a,exclusiveMaximum:C,exclusiveMinimum:o}=g._zod.bag;typeof e=="string"&&e.includes("int")?Q.type="integer":Q.type="number",typeof o=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(Q.minimum=o,Q.exclusiveMinimum=!0):Q.exclusiveMinimum=o),typeof E=="number"&&(Q.minimum=E,typeof o=="number"&&A.target!=="draft-04"&&(o>=E?delete Q.minimum:delete Q.exclusiveMinimum)),typeof C=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(Q.maximum=C,Q.exclusiveMaximum=!0):Q.exclusiveMaximum=C),typeof i=="number"&&(Q.maximum=i,typeof C=="number"&&A.target!=="draft-04"&&(C<=i?delete Q.maximum:delete Q.exclusiveMaximum)),typeof a=="number"&&(Q.multipleOf=a)},cf=(g,A,B,I)=>{B.type="boolean"},Gf=(g,A,B,I)=>{B.not={}},hf=(g,A,B,I)=>{},lf=(g,A,B,I)=>{const Q=g._zod.def,E=Gl(Q.entries);E.every(i=>typeof i=="number")&&(B.type="number"),E.every(i=>typeof i=="string")&&(B.type="string"),B.enum=E},Df=(g,A,B,I)=>{if(A.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},df=(g,A,B,I)=>{if(A.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},wf=(g,A,B,I)=>{const Q=B,E=g._zod.def,{minimum:i,maximum:e}=g._zod.bag;typeof i=="number"&&(Q.minItems=i),typeof e=="number"&&(Q.maxItems=e),Q.type="array",Q.items=HA(E.element,A,{...I,path:[...I.path,"items"]})},Ff=(g,A,B,I)=>{const Q=B,E=g._zod.def;Q.type="object",Q.properties={};const i=E.shape;for(const C in i)Q.properties[C]=HA(i[C],A,{...I,path:[...I.path,"properties",C]});const e=new Set(Object.keys(i)),a=new Set([...e].filter(C=>{const o=E.shape[C]._zod;return A.io==="input"?o.optin===void 0:o.optout===void 0}));a.size>0&&(Q.required=Array.from(a)),E.catchall?._zod.def.type==="never"?Q.additionalProperties=!1:E.catchall?E.catchall&&(Q.additionalProperties=HA(E.catchall,A,{...I,path:[...I.path,"additionalProperties"]})):A.io==="output"&&(Q.additionalProperties=!1)},Mf=(g,A,B,I)=>{const Q=g._zod.def,E=Q.inclusive===!1,i=Q.options.map((e,a)=>HA(e,A,{...I,path:[...I.path,E?"oneOf":"anyOf",a]}));E?B.oneOf=i:B.anyOf=i},Rf=(g,A,B,I)=>{const Q=g._zod.def,E=HA(Q.left,A,{...I,path:[...I.path,"allOf",0]}),i=HA(Q.right,A,{...I,path:[...I.path,"allOf",1]}),e=C=>"allOf"in C&&Object.keys(C).length===1,a=[...e(E)?E.allOf:[E],...e(i)?i.allOf:[i]];B.allOf=a},yf=(g,A,B,I)=>{const Q=B,E=g._zod.def;Q.type="object";const i=E.keyType,a=i._zod.bag?.patterns;if(E.mode==="loose"&&a&&a.size>0){const o=HA(E.valueType,A,{...I,path:[...I.path,"patternProperties","*"]});Q.patternProperties={};for(const t of a)Q.patternProperties[t.source]=o}else(A.target==="draft-07"||A.target==="draft-2020-12")&&(Q.propertyNames=HA(E.keyType,A,{...I,path:[...I.path,"propertyNames"]})),Q.additionalProperties=HA(E.valueType,A,{...I,path:[...I.path,"additionalProperties"]});const C=i._zod.values;if(C){const o=[...C].filter(t=>typeof t=="string"||typeof t=="number");o.length>0&&(Q.required=o)}},uf=(g,A,B,I)=>{const Q=g._zod.def,E=HA(Q.innerType,A,I),i=A.seen.get(g);A.target==="openapi-3.0"?(i.ref=Q.innerType,B.nullable=!0):B.anyOf=[E,{type:"null"}]},mf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType},Sf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType,B.default=JSON.parse(JSON.stringify(Q.defaultValue))},bf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType,A.io==="input"&&(B._prefault=JSON.parse(JSON.stringify(Q.defaultValue)))},pf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType;let i;try{i=Q.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}B.default=i},Yf=(g,A,B,I)=>{const Q=g._zod.def,E=A.io==="input"?Q.in._zod.def.type==="transform"?Q.out:Q.in:Q.out;HA(E,A,I);const i=A.seen.get(g);i.ref=E},Uf=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType,B.readOnly=!0},BD=(g,A,B,I)=>{const Q=g._zod.def;HA(Q.innerType,A,I);const E=A.seen.get(g);E.ref=Q.innerType},ff=Z("ZodISODateTime",(g,A)=>{ZY.init(g,A),mA.init(g,A)});function kf(g){return xU(ff,g)}const Zf=Z("ZodISODate",(g,A)=>{NY.init(g,A),mA.init(g,A)});function Nf(g){return qU(Zf,g)}const Wf=Z("ZodISOTime",(g,A)=>{WY.init(g,A),mA.init(g,A)});function Hf(g){return LU(Wf,g)}const Jf=Z("ZodISODuration",(g,A)=>{HY.init(g,A),mA.init(g,A)});function xf(g){return VU(Jf,g)}const yB=Z("ZodError",(g,A)=>{Fl.init(g,A),g.name="ZodError",Object.defineProperties(g,{format:{value:B=>Sp(g,B)},flatten:{value:B=>mp(g,B)},addIssue:{value:B=>{g.issues.push(B),g.message=JSON.stringify(g.issues,NC,2)}},addIssues:{value:B=>{g.issues.push(...B),g.message=JSON.stringify(g.issues,NC,2)}},isEmpty:{get(){return g.issues.length===0}}})},{Parent:Error}),qf=qC(yB),Lf=LC(yB),Vf=Ri(yB),vf=yi(yB),Xf=Yp(yB),Kf=Up(yB),zf=fp(yB),Tf=kp(yB),Of=Zp(yB),jf=Np(yB),Pf=Wp(yB),_f=Hp(yB),YA=Z("ZodType",(g,A)=>(pA.init(g,A),Object.assign(g["~standard"],{jsonSchema:{input:pi(g,"input"),output:pi(g,"output")}}),g.toJSONSchema=tf(g,{}),g.def=A,g.type=A.type,Object.defineProperty(g,"_def",{value:A}),g.check=(...B)=>g.clone(Yg(A,{checks:[...A.checks??[],...B.map(I=>typeof I=="function"?{_zod:{check:I,def:{check:"custom"},onattach:[]}}:I)]}),{parent:!0}),g.with=g.check,g.clone=(B,I)=>Ug(g,B,I),g.brand=()=>g,g.register=((B,I)=>(B.add(g,I),g)),g.parse=(B,I)=>qf(g,B,I,{callee:g.parse}),g.safeParse=(B,I)=>Vf(g,B,I),g.parseAsync=async(B,I)=>Lf(g,B,I,{callee:g.parseAsync}),g.safeParseAsync=async(B,I)=>vf(g,B,I),g.spa=g.safeParseAsync,g.encode=(B,I)=>Xf(g,B,I),g.decode=(B,I)=>Kf(g,B,I),g.encodeAsync=async(B,I)=>zf(g,B,I),g.decodeAsync=async(B,I)=>Tf(g,B,I),g.safeEncode=(B,I)=>Of(g,B,I),g.safeDecode=(B,I)=>jf(g,B,I),g.safeEncodeAsync=async(B,I)=>Pf(g,B,I),g.safeDecodeAsync=async(B,I)=>_f(g,B,I),g.refine=(B,I)=>g.check(vk(B,I)),g.superRefine=B=>g.check(Xk(B)),g.overwrite=B=>g.check(NI(B)),g.optional=()=>aD(g),g.exactOptional=()=>Yk(g),g.nullable=()=>CD(g),g.nullish=()=>aD(CD(g)),g.nonoptional=B=>Wk(g,B),g.array=()=>zA(g),g.or=B=>TC([g,B]),g.and=B=>uk(g,B),g.transform=B=>tD(g,bk(B)),g.default=B=>kk(g,B),g.prefault=B=>Nk(g,B),g.catch=B=>Jk(g,B),g.pipe=B=>tD(g,B),g.readonly=()=>Lk(g),g.describe=B=>{const I=g.clone();return qQ.add(I,{description:B}),I},Object.defineProperty(g,"description",{get(){return qQ.get(g)?.description},configurable:!0}),g.meta=(...B)=>{if(B.length===0)return qQ.get(g);const I=g.clone();return qQ.add(I,B[0]),I},g.isOptional=()=>g.safeParse(void 0).success,g.isNullable=()=>g.safeParse(null).success,g.apply=B=>B(g),g)),gD=Z("_ZodString",(g,A)=>{VC.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(I,Q,E)=>nf(g,I,Q);const B=g._zod.bag;g.format=B.format??null,g.minLength=B.minimum??null,g.maxLength=B.maximum??null,g.regex=(...I)=>g.check(OU(...I)),g.includes=(...I)=>g.check(_U(...I)),g.startsWith=(...I)=>g.check($U(...I)),g.endsWith=(...I)=>g.check(Af(...I)),g.min=(...I)=>g.check(bi(...I)),g.max=(...I)=>g.check(jl(...I)),g.length=(...I)=>g.check(Pl(...I)),g.nonempty=(...I)=>g.check(bi(1,...I)),g.lowercase=I=>g.check(jU(I)),g.uppercase=I=>g.check(PU(I)),g.trim=()=>g.check(gf()),g.normalize=(...I)=>g.check(Bf(...I)),g.toLowerCase=()=>g.check(If()),g.toUpperCase=()=>g.check(Qf()),g.slugify=()=>g.check(Ef())}),$f=Z("ZodString",(g,A)=>{VC.init(g,A),gD.init(g,A),g.email=B=>g.check(DU(Ak,B)),g.url=B=>g.check(RU(Bk,B)),g.jwt=B=>g.check(JU(Gk,B)),g.emoji=B=>g.check(yU(gk,B)),g.guid=B=>g.check(Kl(ID,B)),g.uuid=B=>g.check(dU(Yi,B)),g.uuidv4=B=>g.check(wU(Yi,B)),g.uuidv6=B=>g.check(FU(Yi,B)),g.uuidv7=B=>g.check(MU(Yi,B)),g.nanoid=B=>g.check(uU(Ik,B)),g.guid=B=>g.check(Kl(ID,B)),g.cuid=B=>g.check(mU(Qk,B)),g.cuid2=B=>g.check(SU(Ek,B)),g.ulid=B=>g.check(bU(ik,B)),g.base64=B=>g.check(NU(nk,B)),g.base64url=B=>g.check(WU(rk,B)),g.xid=B=>g.check(pU(ek,B)),g.ksuid=B=>g.check(YU(ak,B)),g.ipv4=B=>g.check(UU(Ck,B)),g.ipv6=B=>g.check(fU(ok,B)),g.cidrv4=B=>g.check(kU(tk,B)),g.cidrv6=B=>g.check(ZU(sk,B)),g.e164=B=>g.check(HU(ck,B)),g.datetime=B=>g.check(kf(B)),g.date=B=>g.check(Nf(B)),g.time=B=>g.check(Hf(B)),g.duration=B=>g.check(xf(B))});function O(g){return lU($f,g)}const mA=Z("ZodStringFormat",(g,A)=>{yA.init(g,A),gD.init(g,A)}),Ak=Z("ZodEmail",(g,A)=>{uY.init(g,A),mA.init(g,A)}),ID=Z("ZodGUID",(g,A)=>{RY.init(g,A),mA.init(g,A)}),Yi=Z("ZodUUID",(g,A)=>{yY.init(g,A),mA.init(g,A)}),Bk=Z("ZodURL",(g,A)=>{mY.init(g,A),mA.init(g,A)}),gk=Z("ZodEmoji",(g,A)=>{SY.init(g,A),mA.init(g,A)}),Ik=Z("ZodNanoID",(g,A)=>{bY.init(g,A),mA.init(g,A)}),Qk=Z("ZodCUID",(g,A)=>{pY.init(g,A),mA.init(g,A)}),Ek=Z("ZodCUID2",(g,A)=>{YY.init(g,A),mA.init(g,A)}),ik=Z("ZodULID",(g,A)=>{UY.init(g,A),mA.init(g,A)}),ek=Z("ZodXID",(g,A)=>{fY.init(g,A),mA.init(g,A)}),ak=Z("ZodKSUID",(g,A)=>{kY.init(g,A),mA.init(g,A)}),Ck=Z("ZodIPv4",(g,A)=>{JY.init(g,A),mA.init(g,A)}),ok=Z("ZodIPv6",(g,A)=>{xY.init(g,A),mA.init(g,A)}),tk=Z("ZodCIDRv4",(g,A)=>{qY.init(g,A),mA.init(g,A)}),sk=Z("ZodCIDRv6",(g,A)=>{LY.init(g,A),mA.init(g,A)}),nk=Z("ZodBase64",(g,A)=>{VY.init(g,A),mA.init(g,A)}),rk=Z("ZodBase64URL",(g,A)=>{XY.init(g,A),mA.init(g,A)}),ck=Z("ZodE164",(g,A)=>{KY.init(g,A),mA.init(g,A)}),Gk=Z("ZodJWT",(g,A)=>{TY.init(g,A),mA.init(g,A)}),QD=Z("ZodNumber",(g,A)=>{fl.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(I,Q,E)=>rf(g,I,Q),g.gt=(I,Q)=>g.check(Tl(I,Q)),g.gte=(I,Q)=>g.check(KC(I,Q)),g.min=(I,Q)=>g.check(KC(I,Q)),g.lt=(I,Q)=>g.check(zl(I,Q)),g.lte=(I,Q)=>g.check(XC(I,Q)),g.max=(I,Q)=>g.check(XC(I,Q)),g.int=I=>g.check(ED(I)),g.safe=I=>g.check(ED(I)),g.positive=I=>g.check(Tl(0,I)),g.nonnegative=I=>g.check(KC(0,I)),g.negative=I=>g.check(zl(0,I)),g.nonpositive=I=>g.check(XC(0,I)),g.multipleOf=(I,Q)=>g.check(Ol(I,Q)),g.step=(I,Q)=>g.check(Ol(I,Q)),g.finite=()=>g;const B=g._zod.bag;g.minValue=Math.max(B.minimum??Number.NEGATIVE_INFINITY,B.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,g.maxValue=Math.min(B.maximum??Number.POSITIVE_INFINITY,B.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,g.isInt=(B.format??"").includes("int")||Number.isSafeInteger(B.multipleOf??.5),g.isFinite=!0,g.format=B.format??null});function K(g){return vU(QD,g)}const hk=Z("ZodNumberFormat",(g,A)=>{OY.init(g,A),QD.init(g,A)});function ED(g){return XU(hk,g)}const lk=Z("ZodBoolean",(g,A)=>{jY.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>cf(g,B,I)});function zC(g){return KU(lk,g)}const Dk=Z("ZodUnknown",(g,A)=>{PY.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>hf()});function iD(){return zU(Dk)}const dk=Z("ZodNever",(g,A)=>{_Y.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Gf(g,B,I)});function wk(g){return TU(dk,g)}const Fk=Z("ZodArray",(g,A)=>{$Y.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>wf(g,B,I,Q),g.element=A.element,g.min=(B,I)=>g.check(bi(B,I)),g.nonempty=B=>g.check(bi(1,B)),g.max=(B,I)=>g.check(jl(B,I)),g.length=(B,I)=>g.check(Pl(B,I)),g.unwrap=()=>g.element});function zA(g,A){return ef(Fk,g,A)}const Mk=Z("ZodObject",(g,A)=>{BU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Ff(g,B,I,Q),lA(g,"shape",()=>A.shape),g.keyof=()=>fi(Object.keys(g._zod.def.shape)),g.catchall=B=>g.clone({...g._zod.def,catchall:B}),g.passthrough=()=>g.clone({...g._zod.def,catchall:iD()}),g.loose=()=>g.clone({...g._zod.def,catchall:iD()}),g.strict=()=>g.clone({...g._zod.def,catchall:wk()}),g.strip=()=>g.clone({...g._zod.def,catchall:void 0}),g.extend=B=>Fp(g,B),g.safeExtend=B=>Mp(g,B),g.merge=B=>Rp(g,B),g.pick=B=>dp(g,B),g.omit=B=>wp(g,B),g.partial=(...B)=>yp(eD,g,B[0]),g.required=(...B)=>up(oD,g,B[0])});function wA(g,A){const B={type:"object",shape:g??{},...gA(A)};return new Mk(B)}const Rk=Z("ZodUnion",(g,A)=>{gU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Mf(g,B,I,Q),g.options=A.options});function TC(g,A){return new Rk({type:"union",options:g,...gA(A)})}const yk=Z("ZodIntersection",(g,A)=>{IU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Rf(g,B,I,Q)});function uk(g,A){return new yk({type:"intersection",left:g,right:A})}const mk=Z("ZodRecord",(g,A)=>{QU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>yf(g,B,I,Q),g.keyType=A.keyType,g.valueType=A.valueType});function Ui(g,A,B){return new mk({type:"record",keyType:g,valueType:A,...gA(B)})}const OC=Z("ZodEnum",(g,A)=>{EU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(I,Q,E)=>lf(g,I,Q),g.enum=A.entries,g.options=Object.values(A.entries);const B=new Set(Object.keys(A.entries));g.extract=(I,Q)=>{const E={};for(const i of I)if(B.has(i))E[i]=A.entries[i];else throw new Error(`Key ${i} not found in enum`);return new OC({...A,checks:[],...gA(Q),entries:E})},g.exclude=(I,Q)=>{const E={...A.entries};for(const i of I)if(B.has(i))delete E[i];else throw new Error(`Key ${i} not found in enum`);return new OC({...A,checks:[],...gA(Q),entries:E})}});function fi(g,A){const B=Array.isArray(g)?Object.fromEntries(g.map(I=>[I,I])):g;return new OC({type:"enum",entries:B,...gA(A)})}const Sk=Z("ZodTransform",(g,A)=>{iU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>df(g,B),g._zod.parse=(B,I)=>{if(I.direction==="backward")throw new rl(g.constructor.name);B.addIssue=E=>{if(typeof E=="string")B.issues.push(xQ(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=g),B.issues.push(xQ(i))}};const Q=A.transform(B.value,B);return Q instanceof Promise?Q.then(E=>(B.value=E,B)):(B.value=Q,B)}});function bk(g){return new Sk({type:"transform",transform:g})}const eD=Z("ZodOptional",(g,A)=>{xl.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>BD(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function aD(g){return new eD({type:"optional",innerType:g})}const pk=Z("ZodExactOptional",(g,A)=>{eU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>BD(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Yk(g){return new pk({type:"optional",innerType:g})}const Uk=Z("ZodNullable",(g,A)=>{aU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>uf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function CD(g){return new Uk({type:"nullable",innerType:g})}const fk=Z("ZodDefault",(g,A)=>{CU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Sf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType,g.removeDefault=g.unwrap});function kk(g,A){return new fk({type:"default",innerType:g,get defaultValue(){return typeof A=="function"?A():dl(A)}})}const Zk=Z("ZodPrefault",(g,A)=>{oU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>bf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Nk(g,A){return new Zk({type:"prefault",innerType:g,get defaultValue(){return typeof A=="function"?A():dl(A)}})}const oD=Z("ZodNonOptional",(g,A)=>{tU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>mf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Wk(g,A){return new oD({type:"nonoptional",innerType:g,...gA(A)})}const Hk=Z("ZodCatch",(g,A)=>{sU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>pf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType,g.removeCatch=g.unwrap});function Jk(g,A){return new Hk({type:"catch",innerType:g,catchValue:typeof A=="function"?A:()=>A})}const xk=Z("ZodPipe",(g,A)=>{nU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Yf(g,B,I,Q),g.in=A.in,g.out=A.out});function tD(g,A){return new xk({type:"pipe",in:g,out:A})}const qk=Z("ZodReadonly",(g,A)=>{rU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Uf(g,B,I,Q),g.unwrap=()=>g._zod.def.innerType});function Lk(g){return new qk({type:"readonly",innerType:g})}const Vk=Z("ZodCustom",(g,A)=>{cU.init(g,A),YA.init(g,A),g._zod.processJSONSchema=(B,I,Q)=>Df(g,B)});function vk(g,A={}){return af(Vk,g,A)}function Xk(g){return Cf(g)}const Kk=Sg.map(g=>g),sD=wA({id:O(),uuid:O(),playlist_index:K().nonnegative(),chain_name:O(),token_address:O().optional(),token_id:O().optional(),tx_id:O().optional(),platform:O(),title:O(),artist:O(),description:O().optional(),album:O().optional(),image_url:O().url(),image_thumb_url:O().url().optional(),audio_url:O().url(),audio_url_lossless:O().url().optional(),duration:K().nonnegative(),genre:O(),tags:zA(O()),bpm:K().positive().optional(),key:O().optional(),attributes:Ui(O(),TC([O(),K()])).optional()}).refine(g=>g.chain_name==="AR"?!!g.tx_id:!!g.token_address&&!!g.token_id,{message:"AR chain tracks must have tx_id; other chains must have token_address and token_id",path:["chain_name"]}),zk=wA({name:O(),description:O().optional(),image:O().url(),creator:O(),genre:O().optional(),tags:zA(O()).optional(),tracks:zA(sD)}),Tk=wA({bass_dominance:K().min(0).max(1),mid_dominance:K().min(0).max(1),treble_dominance:K().min(0).max(1),average_amplitude:K().min(0).max(1),spectral_centroid:K().optional(),spectral_rolloff:K().optional(),zero_crossing_rate:K().optional(),color_palette:wA({colors:zA(O()),primary_color:O(),secondary_color:O().optional(),accent_color:O().optional(),brightness:K().min(0).max(1),saturation:K().min(0).max(1),is_monochrome:zC()}).optional(),analysis_metadata:wA({duration_analyzed:K().positive(),full_buffer_analyzed:zC(),sample_positions:zA(K()),analyzed_at:O()})}),jC=wA({STR:K().min(1).max(20),DEX:K().min(1).max(20),CON:K().min(1).max(20),INT:K().min(1).max(20),WIS:K().min(1).max(20),CHA:K().min(1).max(20)}),Ok=wA({name:O(),race:fi(["Human","Elf","Dwarf","Halfling","Dragonborn","Gnome","Half-Elf","Half-Orc","Tiefling"]),class:fi(Kk),level:K().min(1).max(20),ability_scores:jC,ability_modifiers:jC,proficiency_bonus:K().min(2).max(6),hp:wA({current:K().nonnegative(),max:K().positive(),temp:K().nonnegative()}),armor_class:K().positive(),initiative:K(),speed:K().positive(),skills:Ui(O(),fi(["none","proficient","expertise"])),saving_throws:Ui(O(),zC()),racial_traits:zA(O()),class_features:zA(O()),spells:wA({spell_slots:Ui(O(),wA({total:K().nonnegative(),used:K().nonnegative()})),known_spells:zA(O()),cantrips:zA(O())}).optional(),equipment:wA({weapons:zA(O()),armor:zA(O()),items:zA(O())}).optional(),appearance:wA({body_type:O(),skin_tone:O(),hair_style:O(),hair_color:O(),eye_color:O(),facial_features:zA(O()),primary_color:O().optional(),secondary_color:O().optional(),aura_color:O().optional()}).optional(),xp:wA({current:K().nonnegative(),next_level:K().positive()}),seed:O(),generated_at:O()});var nD=(g=>(g[g.DEBUG=0]="DEBUG",g[g.INFO=1]="INFO",g[g.WARN=2]="WARN",g[g.ERROR=3]="ERROR",g[g.NONE=4]="NONE",g))(nD||{});const jk={0:"DEBUG",1:"INFO",2:"WARN",3:"ERROR",4:"NONE"};let PB=1,PC=!0,_C=!0,ki=null,Zi=!1,LQ=!1;class VA{constructor(A){this.context=A}static for(A){return new VA(A)}static enableDiagnosticMode(){Zi=!0,PB=0}static disableDiagnosticMode(){Zi=!1,PB=1}static isDiagnosticMode(){return Zi}static enableVerbose(){LQ=!0,PB=0}static disableVerbose(){LQ=!1,PB=1}static isVerbose(){return LQ}static setVerbose(A){LQ=A,PB=A?0:1}static setLevel(A){PB=A}static getLevel(){return PB}static configure(A){A.level!==void 0&&(PB=A.level),A.includeTimestamp!==void 0&&(PC=A.includeTimestamp),A.includeContext!==void 0&&(_C=A.includeContext),A.customHandler!==void 0&&(ki=A.customHandler)}static reset(){PB=1,PC=!0,_C=!0,ki=null,Zi=!1,LQ=!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,I){if(A<PB)return;const Q={timestamp:new Date,level:A,context:this.context,message:B,data:I};if(ki){ki(Q);return}const E=this.formatMessage(Q);switch(A){case 0:I!==void 0?console.debug(E,I):console.debug(E);break;case 1:I!==void 0?console.info(E,I):console.info(E);break;case 2:I!==void 0?console.warn(E,I):console.warn(E);break;case 3:I!==void 0?console.error(E,I):console.error(E);break}}formatMessage(A){const B=[];return PC&&B.push(this.formatTimestamp(A.timestamp)),B.push(`[${jk[A.level]}]`),_C&&A.context&&B.push(`[${A.context}]`),B.push(A.message),B.join(" ")}formatTimestamp(A){const B=A.getHours().toString().padStart(2,"0"),I=A.getMinutes().toString().padStart(2,"0"),Q=A.getSeconds().toString().padStart(2,"0"),E=A.getMilliseconds().toString().padStart(3,"0");return`${B}:${I}:${Q}.${E}`}}function Pk(g){return VA.for(g)}class eA{static extractAudioUrl(A){const B=["mp3_url","mp3Url","lossy_audio","lossyAudio","animation_url","animationUrl","audio_url","audioUrl","lossless_audio","losslessAudio","audio","multimedia_url","multimediaUrl"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];return null}static extractAudioUrlLossless(A){const B=["lossless_audio","losslessAudio","wav_url","wavUrl","flac_url","flacUrl","audio_url","audioUrl"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];return null}static extractImageUrl(A){const B=["image_small","imageSmall","image","image_large","imageLarge","image_thumb","imageThumb","image_url","imageUrl","image_uri","imageUri","image_preview","imagePreview"];for(const Q of B)if(A[Q]&&typeof A[Q]=="string")return A[Q];const I=[this.extractNestedUri(A,"artwork","uri"),this.extractNestedUri(A,"project","artwork","uri"),this.extractNestedUri(A,"primaryMedia","uri")];for(const Q of I)if(Q)return Q;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","artist_name","artistName","album_artist","albumArtist","created_by","createdBy","minter"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];if(Array.isArray(A.attributes)){const I=A.attributes.find(Q=>Q.trait_type?.toLowerCase()==="artist"&&Q.value!==void 0);if(I&&typeof I.value=="string")return I.value}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(I=>I.trait_type?.toLowerCase()==="genre"&&I.value!==void 0);if(B){if(typeof B.value=="string")return B.value;if(Array.isArray(B.value)&&B.value.length>0){const I=B.value[0];return typeof I=="string"?I:""}}}return""}static convertAttributes(A){if(!Array.isArray(A))return null;const B={};for(const I of A)I.trait_type&&I.value!==void 0&&(B[I.trait_type]=I.value);return Object.keys(B).length>0?B:null}static extractNestedUri(A,...B){let I=A;for(const Q of B)if(I&&typeof I=="object"&&!Array.isArray(I))I=I[Q];else return null;return typeof I=="string"?I:null}}function $C(g){if("audio_url"in g&&typeof g.audio_url=="string")return g.audio_url;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A)return eA.extractAudioUrl(A)}return null}function _k(g){if("audio_url_lossless"in g&&typeof g.audio_url_lossless=="string")return g.audio_url_lossless;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A)return eA.extractAudioUrlLossless(A)}return null}function Ao(g){if("image_url"in g&&typeof g.image_url=="string")return g.image_url;if("metadata"in g){if("artwork_url"in g&&typeof g.artwork_url=="string")return g.artwork_url;const A=eA.parseMetadata(g.metadata);if(A)return eA.extractImageUrl(A)}return null}function rD(g){if("image_thumb_url"in g&&typeof g.image_thumb_url=="string")return g.image_thumb_url;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A)return eA.extractImageThumbUrl(A)}return null}function cD(g){if("audio_url"in g)return null;if("metadata"in g){const A=eA.parseMetadata(g.metadata);if(A&&typeof A.vrm=="string"&&A.vrm)return A.vrm}return null}function $k(g){const A=[];for(const B of g.tracks){const I=$C(B);I&&A.push(I)}return A}function AZ(g){const A=[];for(const B of g.tracks){const I=Ao(B);I&&A.push(I)}return A}function BZ(g){const A=[];for(const B of g.tracks){if("title"in B&&typeof B.title=="string"){A.push(B.title);continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I){const Q=eA.extractTitle(I);Q&&A.push(Q)}}}return A}function gZ(g){const A=[];for(const B of g.tracks){if("artist"in B&&typeof B.artist=="string"){A.push(B.artist);continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I){const Q=eA.extractArtist(I);Q&&A.push(Q)}}}return A}function IZ(g){const A=new Set;for(const B of g.tracks){if("genre"in B&&typeof B.genre=="string"&&B.genre){A.add(B.genre);continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);I&&typeof I.genre=="string"&&I.genre&&A.add(I.genre)}}return Array.from(A).sort()}function QZ(g){const A=new Set;for(const B of g.tracks){if("tags"in B&&Array.isArray(B.tags)){for(const I of B.tags)I&&A.add(I.toLowerCase());continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I&&Array.isArray(I.tags))for(const Q of I.tags)Q&&A.add(String(Q).toLowerCase())}}return Array.from(A).sort()}function EZ(g){let A=0;for(const B of g.tracks){if("duration"in B&&typeof B.duration=="number"){A+=B.duration;continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);I&&typeof I.duration=="number"&&(A+=I.duration)}}return A}function iZ(g){return g.tracks.length}function eZ(g){const A=[];for(const B of g.tracks){const I=$C(B),Q=Ao(B),E=rD(B);let i="",e="";if("title"in B)i=B.title||"",e=B.artist||"";else if("metadata"in B){const a=eA.parseMetadata(B.metadata);a&&(i=eA.extractTitle(a)||"",e=eA.extractArtist(a)||"")}if(I){const a={title:i,artist:e,audio_url:I,image_url:Q||""},C=_k(B);C&&C!==I&&(a.audio_url_lossless=C),E&&(a.image_thumb_url=E),"audio_ipfs_hash"in B&&typeof B.audio_ipfs_hash=="string"&&(a.audio_ipfs_hash=B.audio_ipfs_hash),"artwork_ipfs_hash"in B&&typeof B.artwork_ipfs_hash=="string"&&(a.artwork_ipfs_hash=B.artwork_ipfs_hash),A.push(a)}}return A}function aZ(g){const A=[];for(const B of g.tracks){if("audio_url"in B){A.push({...B});continue}if("metadata"in B){const I=eA.parseMetadata(B.metadata);if(I){const Q=eA.extractAudioUrlLossless(I),E=eA.extractAudioUrl(I);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:eA.extractTitle(I),artist:eA.extractArtist(I),audio_url:E,image_url:eA.extractImageUrl(I),image_thumb_url:eA.extractImageThumbUrl(I),duration:I.duration,genre:I.genre,tags:I.tags,bpm:I.bpm,key:I.key,album:I.album,description:I.description,attributes:eA.convertAttributes(I.attributes),...Q&&Q!==E?{audio_url_lossless:Q}:{},...B.audio_ipfs_hash?{audio_ipfs_hash:B.audio_ipfs_hash}:{},...B.artwork_ipfs_hash?{artwork_ipfs_hash:B.artwork_ipfs_hash}:{}})}}}return A}function CZ(g){const A=[];for(const B of g.tracks){const I=cD(B);I&&A.push(I)}return A}function oZ(g){const A=[];for(const B of g.tracks){const I=cD(B);if(!I)continue;const Q=$C(B),E=Ao(B),i=rD(B);let e="",a="";if("title"in B)e=B.title||"",a=B.artist||"";else if("metadata"in B){const o=eA.parseMetadata(B.metadata);o&&(e=eA.extractTitle(o)||"",a=eA.extractArtist(o)||"")}const C={title:e,artist:a,audio_url:Q||"",image_url:E||"",vrm:I};i&&(C.image_thumb_url=i),A.push(C)}return A}const Bo=[{host:"arweave.net",protocol:"https",priority:3},{host:"ardrive.net",protocol:"https",priority:2},{host:"turbo-gateway.com",protocol:"https",priority:1}],go=["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 WI(g){if(!g||typeof g!="string")return!1;if(g.startsWith("ar://"))return!0;const A=g.toLowerCase();try{const B=new URL(g).hostname;return go.some(I=>B===I||B.endsWith("."+I))}catch{return go.some(B=>A.includes(B))}}function HI(g){if(!g||typeof g!="string"||!WI(g))return null;let A=null,B="";if(g.startsWith("ar://")){const i=g.slice(5),e=i.indexOf("/");return e!==-1?(A=i.slice(0,e),B=i.slice(e)):A=i,A.length===43&&/^[A-Za-z0-9_-]+$/.test(A)?{txId:A,originalUrl:g,pathSuffix:B}:null}let I=g;try{const i=new URL(g);I=i.pathname+i.search}catch{}const Q=/[A-Za-z0-9_-]{43}/g,E=I.match(Q);if(E&&E.length>0){A=E[0];const i=g.indexOf(A);if(i!==-1){const e=g.slice(i+43),a=Math.min(e.indexOf("?")===-1?1/0:e.indexOf("?"),e.indexOf("#")===-1?1/0:e.indexOf("#"));a===1/0?B=e:B=e.slice(0,a)}return{txId:A,originalUrl:g,pathSuffix:B}}return null}function VB(g,A,B=""){return`${A.protocol||"https"}://${A.host}/${g}${B}`}function tZ(g,A=Bo,B=""){return A.sort((I,Q)=>I.priority-Q.priority).map(I=>VB(g,I,B))}async function sZ(){try{return await import("@ar.io/wayfinder-core")}catch{return null}}async function nZ(){try{return await import("@ar.io/sdk")}catch{return null}}const rZ="https://solana-rpc.publicnode.com",cZ=5e3,GZ=864e5,Io="arweave_active_gateway",Qo="arweave_ranked_gateways";class GD{constructor(A){this.cache=new Map,this.logger=VA.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.wayfinderGatewaysProvider=null,this.rankedGatewaysCache=null,this.rankedGatewaysCacheTimestamp=0,this.RANKED_GATEWAYS_TTL_MS=7200*1e3,this.activeGateway=null,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.gateways=(A?.gateways??Bo).map(I=>({...I})),this.timeout=A?.timeout??cZ,this.cacheTTL=A?.cacheTTL??GZ,this.slowResponseThreshold=A?.slowResponseThreshold??8e3,this.maxSlowResponses=A?.maxSlowResponses??3,this.solanaRpcUrl=A?.solanaRpcUrl??rZ,this.hasCustomSolanaRpc=typeof A?.solanaRpcUrl=="string"&&A.solanaRpcUrl.length>0,this.wayfinderSortBy=A?.wayfinderSortBy??"weights.compositeWeight",this.wayfinderPrimaryLimit=A?.wayfinderPrimaryLimit??50,this.wayfinderFallbackLimit=A?.wayfinderFallbackLimit??100,this.wayfinderStrategy=A?.wayfinderStrategy??"composite-ping-random",this.gateways.sort((I,Q)=>I.priority-Q.priority),this.gateways.forEach(I=>{this.originalPriorities.set(I.host,I.priority)}),this.activeGateway=this.loadPersistedGateway();const B=this.loadPersistedRankedGateways();B&&(this.rankedGatewaysCache=B),Promise.all([sZ(),nZ(),Promise.resolve().then(()=>HK)]).then(([I,Q,E])=>{if(I&&Q)try{const{FastestPingRoutingStrategy:i,RandomRoutingStrategy:e,CompositeRoutingStrategy:a,RoundRobinRoutingStrategy:C,NetworkGatewaysProvider:o}=I,t=Q.ARIO,s=E.createSolanaRpc(this.solanaRpcUrl),n=t.init({rpc:s}),r=new o({ario:n,sortBy:this.wayfinderSortBy,limit:this.wayfinderPrimaryLimit}),c=new o({ario:n,sortBy:this.wayfinderSortBy,limit:this.wayfinderFallbackLimit});this.wayfinderGatewaysProvider=r;const G=(()=>{switch(this.wayfinderStrategy){case"random-only":return new e({gatewaysProvider:c});case"ping-only":return new i({timeoutMs:3e3,gatewaysProvider:r});case"round-robin":return new C({gateways:[],gatewaysProvider:r});default:return new a({strategies:[new i({timeoutMs:3e3,gatewaysProvider:r}),new e({gatewaysProvider:c})]})}})();this.wayfinder=I.createWayfinderClient({routingStrategy:G}),this.logger.info("Wayfinder client initialized",{strategy:this.wayfinderStrategy,sortBy:this.wayfinderSortBy,primaryLimit:this.wayfinderPrimaryLimit,fallbackLimit:this.wayfinderFallbackLimit})}catch(i){this.logger.warn("Failed to configure Wayfinder routing strategy, using defaults",{error:i}),this.wayfinder=I.createWayfinderClient(),this.logger.info("Wayfinder client initialized with default routing")}else I&&(this.wayfinder=I.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(I=>I.host),timeout:this.timeout,cacheTTL:this.cacheTTL,activeGateway:this.activeGateway?.host??null})}withTimeout(A,B,I){return new Promise((Q,E)=>{const i=setTimeout(()=>E(new Error(I)),B);A.then(e=>{clearTimeout(i),Q(e)},e=>{clearTimeout(i),E(e)})})}resolveUrlSimple(A){if(!WI(A))return A;const B=HI(A);if(!B)return A;const I=this.activeGateway??this.gateways[0];return this.logger.debug("[gateway] resolveUrlSimple",{txId:B.txId,gateway:I.host,pathSuffix:B.pathSuffix||void 0}),VB(B.txId,I,B.pathSuffix)}setPreferredGateway(A){const B=this.gateways.find(I=>I.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(I=>I.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 I=this.healthData.get(B.host)??[],Q=I.length,E=Q>0?Math.round(I.reduce((e,a)=>e+a.responseTime,0)/Q):0,i=Q>0?I.filter(e=>e.success).length/Q:1;return{host:B.host,avgMs:E,successRate:Math.round(i*100)/100,checks:Q}});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 I=B?.signal;if(I?.aborted)return this.logger.debug("resolveUrl called with already-aborted signal, returning original URL"),A;if(!WI(A))return A;const Q=HI(A);if(!Q)return this.logger.warn("Failed to parse Arweave URL, returning original",{url:A}),A;const{txId:E,pathSuffix:i}=Q,e=this.getCachedGateway(E);if(e){this.hitCount++;const s=VB(E,e,i);return this.logger.debug("Cache hit for txId",{txId:E,gateway:e.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 C=this.inflightResolves.get(E);if(C)return this.logger.debug("Reusing in-flight resolve for txId",{txId:E}),C;const o=new AbortController;I&&I.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,I,Q,E){const i=Date.now(),e=E?.bypassArweaveNet??!1;let a=null;if(A.startsWith("https://")||A.startsWith("http://"))try{const r=new URL(A),c={host:r.host,protocol:r.protocol.replace(":",""),priority:0},G=Date.now(),D=await this.checkAndSetGateway(A,B,I,c,Q),h=Date.now()-G;if(D)return this.logger.info("[gateway] Step 0 (original): success",{host:c.host,ms:h,totalMs:Date.now()-i}),D;this.logger.info("[gateway] Step 0 (original): failed",{host:c.host,ms:h}),a=c.host}catch{}if(this.activeGateway&&this.activeGateway.host!==a){const r=Date.now(),c=await this.checkAndSetGateway(A,B,I,this.activeGateway,Q),G=Date.now()-r;if(c)return this.logger.info("[gateway] Step 1 (persisted): success",{host:this.activeGateway.host,ms:G,totalMs:Date.now()-i}),c;this.logger.info("[gateway] Step 1 (persisted): failed, clearing",{ms:G}),this.activeGateway=null,this.clearPersistedGateway()}if(!e&&a!=="arweave.net"){const r=this.gateways.find(c=>c.host==="arweave.net");if(r){const c=Date.now(),G=await this.checkAndSetGateway(A,B,I,r,Q),D=Date.now()-c;if(G)return this.logger.info("[gateway] Step 2 (arweave.net): success",{ms:D,totalMs:Date.now()-i}),G;this.logger.info("[gateway] Step 2 (arweave.net): failed",{ms:D})}}const C=Date.now(),o=await this.tryFallbackGateways(A,B,I,Q,a),t=Date.now()-C;if(o)return this.logger.info("[gateway] Step 3 (fallbacks): success",{ms:t,totalMs:Date.now()-i}),o;this.logger.info("[gateway] Step 3 (fallbacks): failed",{ms:t});const s=!this.hasCustomSolanaRpc,n=E?.bypassWayfinder??s;if(this.wayfinder&&!n){const r=Date.now();this.logger.info("[gateway] Step 4 (wayfinder): trying");const c=await this.tryWayfinder(B,I,Q,a),G=Date.now()-r;if(c)return this.logger.info("[gateway] Step 4 (wayfinder): success",{ms:G,totalMs:Date.now()-i}),c;this.logger.info("[gateway] Step 4 (wayfinder): failed",{ms:G})}return this.logger.warn("All gateways (arweave.net + Wayfinder + fallbacks) failed, returning original URL",{txId:B,pathSuffix:I,originalUrl:A}),A}async reportGatewayFailure(A,B){const{signal:I,reason:Q,excludeHost:E}=B??{};if(I?.aborted)return this.logger.debug("reportGatewayFailure called with already-aborted signal, returning original URL"),A;if(Q==="user-cancel-fast")return this.logger.debug("User cancelled quickly, keeping current gateway"),A;const i=HI(A);if(!i)return A;const{txId:e,pathSuffix:a}=i;this.logger.warn("Gateway failure reported, finding new gateway",{failedHost:this.activeGateway?.host,txId:e,reason:Q??"load-error"});const C=this.activeGateway?.host??E;this.activeGateway=null,this.cache.delete(e),this.clearPersistedGateway();const o=this.gateways.find(n=>n.host==="arweave.net"&&n.host!==C);if(o){const n=await this.checkAndSetGateway(A,e,a,o,I);if(n)return n}if(this.wayfinder){const n=await this.tryWayfinder(e,a,I);if(n)return n}const t=this.gateways;C&&(this.gateways=this.gateways.filter(n=>n.host!==C));const s=await this.tryFallbackGateways(A,e,a,I);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,I,Q,E){if(E?.aborted)return null;const i=await this.checkGateway(B,Q,I,E);if(i===!0){this.setActiveGateway(Q,B);const e=VB(B,Q,I);return this.logger.info("Gateway resolved",{txId:B,gateway:Q.host,pathSuffix:I,workingUrl:e}),e}if(i==="maybe"){const e=VB(B,Q,I);return this.logger.info("Gateway maybe resolved (no-cors)",{txId:B,gateway:Q.host,pathSuffix:I,workingUrl:e}),e}return null}async tryFallbackGateways(A,B,I,Q,E){this.missCount++;const i=.7,e=3,a=this.gateways.filter(n=>n.host!=="arweave.net"&&n.host!==E),C=a.filter(n=>{const{rate:r,totalChecks:c}=this.getFailureRate(n.host);return!(c>=e&&r>i)}),o=C.length>0?C:a;if(Q?.aborted||o.length===0)return null;const t=async n=>{if(Q?.aborted||n.length===0)return null;const r=new AbortController,c=()=>r.abort();Q?.addEventListener("abort",c,{once:!0});let G=!1;try{return await Promise.any(n.map(async h=>{const w=await this.checkGateway(B,h,I,r.signal);if(w){const y=VB(B,h,I);return G||(G=!0,w===!0?(this.setActiveGateway(h,B),this.logger.info("Gateway resolved via fallback",{txId:B,gateway:h.host,pathSuffix:I,workingUrl:y})):this.logger.info("Gateway maybe resolved via fallback (no-cors)",{txId:B,gateway:h.host,pathSuffix:I,workingUrl:y})),y}throw new Error(`Gateway ${h.host} failed check`)}))}catch{return null}finally{Q?.removeEventListener("abort",c)}},s=await t(o);if(s)return s;if(C.length<a.length&&!Q?.aborted){const n=a.filter(c=>!C.some(G=>G.host===c.host)).map(c=>c.host);this.logger.debug("Healthy gateways exhausted, retrying with previously unhealthy",{excludedHosts:n});const r=await t(a);if(r)return r}return null}async getRankedGatewaysCached(A){if(!this.wayfinderGatewaysProvider)return null;const B=Date.now(),I=B-this.rankedGatewaysCacheTimestamp;if(this.rankedGatewaysCache&&I<this.RANKED_GATEWAYS_TTL_MS)return this.logger.debug("Reusing cached ranked gateway list",{size:this.rankedGatewaysCache.length,ageMs:I}),this.rankedGatewaysCache;try{const Q=await this.withTimeout(this.wayfinderGatewaysProvider.getGateways(),this.timeout+2e3,"Wayfinder provider getGateways timed out");return A?.aborted?null:(this.rankedGatewaysCache=Q,this.rankedGatewaysCacheTimestamp=B,this.persistRankedGateways(Q,B),this.logger.info("Refreshed ranked gateway list cache",{size:Q.length}),Q)}catch(Q){return this.logger.debug("Failed to fetch ranked gateway list from provider",{error:Q}),this.rankedGatewaysCache?(this.logger.debug("Falling back to stale ranked gateway cache",{size:this.rankedGatewaysCache.length,ageMs:I}),this.rankedGatewaysCache):null}}async tryWayfinder(A,B,I,Q){if(!this.wayfinder)return null;const E=10,i=new Set;Q&&i.add(Q);const e=`https://arweave.net/${A}${B}`;try{this.logger.debug("Resolving via Wayfinder (first pick)",{txId:A,normalizedUrl:e});const o=await this.withTimeout(this.wayfinder.resolveUrl({originalUrl:e}),this.timeout+2e3,"Wayfinder resolution timed out");if(I?.aborted)return null;const t=o.hostname;if(i.has(t))this.logger.debug("Wayfinder first pick was already excluded, skipping to walk",{host:t});else{const s=o.protocol.replace(":",""),n={host:t,protocol:s,priority:0},r=await this.checkGateway(A,n,B,I);if(r){const c=VB(A,n,B);return r===!0?(this.setActiveGateway(n,A),this.logger.info("Gateway resolved via Wayfinder (first pick)",{txId:A,gateway:t,pathSuffix:B,workingUrl:c})):this.logger.info("Gateway maybe resolved via Wayfinder (first pick, no-cors)",{txId:A,gateway:t,pathSuffix:B,workingUrl:c}),c}this.logger.debug("Wayfinder first pick failed verify, will walk ranked list",{host:t}),i.add(t)}}catch(o){this.logger.debug("Wayfinder first pick threw, will walk ranked list",{error:o})}if(I?.aborted)return null;const a=await this.getRankedGatewaysCached(I);if(!a||a.length===0||I?.aborted)return null;const C=a.filter(o=>!i.has(o.hostname)).slice(0,E);this.logger.debug("Walking Wayfinder ranked list",{txId:A,poolSize:a.length,walkSize:C.length});for(const o of C){if(I?.aborted)return null;const t={host:o.hostname,protocol:o.protocol.replace(":",""),priority:0},s=await this.checkGateway(A,t,B,I);if(s){const n=VB(A,t,B);return s===!0?(this.setActiveGateway(t,A),this.logger.info("Gateway resolved via Wayfinder ranked walk",{txId:A,gateway:t.host,pathSuffix:B,workingUrl:n})):this.logger.info("Gateway maybe resolved via Wayfinder ranked walk (no-cors)",{txId:A,gateway:t.host,pathSuffix:B,workingUrl:n}),n}i.add(t.host)}return this.logger.debug("Wayfinder ranked walk exhausted with no match",{txId:A,checkedHosts:Array.from(i)}),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(Io);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:Q,...E}=B;return E}}catch{}return null}loadPersistedRankedGateways(){try{if(typeof localStorage>"u")return null;const A=localStorage.getItem(Qo);if(!A)return null;const B=JSON.parse(A);if(!B||!Array.isArray(B.gateways)||typeof B.timestamp!="number")return null;const I=Date.now()-B.timestamp;if(I>this.RANKED_GATEWAYS_TTL_MS)return this.logger.info("Ignoring persisted ranked gateway list — expired",{ageMs:I}),this.clearPersistedRankedGateways(),null;const Q=[];for(const E of B.gateways)if(typeof E=="string")try{Q.push(new URL(E))}catch{}return Q.length===0?null:(this.rankedGatewaysCacheTimestamp=B.timestamp,this.logger.info("Restored ranked gateway list from localStorage",{size:Q.length,ageMs:I}),Q)}catch{return null}}persistRankedGateways(A,B){try{if(typeof localStorage>"u")return;const I={gateways:A.map(Q=>Q.toString()),timestamp:B};localStorage.setItem(Qo,JSON.stringify(I))}catch{}}clearPersistedRankedGateways(){try{if(typeof localStorage>"u")return;localStorage.removeItem(Qo)}catch{}}persistGateway(A){try{if(typeof localStorage>"u")return;const B={...A,timestamp:Date.now()};localStorage.setItem(Io,JSON.stringify(B))}catch{}}clearPersistedGateway(){try{if(typeof localStorage>"u")return;localStorage.removeItem(Io)}catch{}}async checkGateway(A,B,I="",Q){const E=VB(A,B,I),i=Date.now(),e=new AbortController,a=setTimeout(()=>e.abort(),this.timeout),C=()=>e.abort();Q?.addEventListener("abort",C,{once:!0});try{const o=await fetch(E,{method:"HEAD",mode:"cors",signal:e.signal});clearTimeout(a),Q?.removeEventListener("abort",C);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),Q?.removeEventListener("abort",C);const t=Date.now()-i;if(this.recordGatewayResponse(B.host,t,!1),o instanceof Error&&o.name==="AbortError"){const s=Q?.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:e.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 I={txId:A,workingGateway:B,timestamp:Date.now(),ttl:this.cacheTTL};this.cache.set(A,I),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(!WI(A))return;const B=HI(A);B&&(this.cache.delete(B.txId),this.activeGateway=null,this.clearPersistedGateway())}async prefetchUrls(A,B){const I=B?.concurrency??5,Q=B?.continueOnError??!0,E=[];let i=0,e=0,a=0;for(let C=0;C<A.length;C+=I){const o=A.slice(C,C+I),t=await Promise.allSettled(o.map(async s=>{if(!WI(s))return{url:s,txId:"",success:!1,error:"Not an Arweave URL"};const n=HI(s);if(!n)return{url:s,txId:"",success:!1,error:"Failed to parse Arweave URL"};const r=this.getCachedGateway(n.txId);if(r)return{url:s,txId:n.txId,success:!0,gateway:r};await this.resolveUrl(s);const c=this.getCachedGateway(n.txId);return c?{url:s,txId:n.txId,success:!0,gateway:c}:{url:s,txId:n.txId,success:!1,error:"All gateways failed"}}));for(const s of t)if(s.status==="fulfilled"){const n=s.value;E.push(n),n.error==="Not an Arweave URL"?a++:n.success?i++:e++}else e++,E.push({url:"unknown",txId:"",success:!1,error:s.reason?.message??"Unknown error"});if(!Q&&e>0){this.logger.warn("Prefetch stopped due to failures",{failed:e,processed:E.length});break}}return this.logger.info("Prefetch complete",{total:A.length,succeeded:i,failed:e,skipped:a}),{total:A.length,succeeded:i,failed:e,skipped:a,entries:E}}getCacheStats(){const A=Array.from(this.cache.entries()),B=Date.now(),I=A.filter(([,Q])=>B-Q.timestamp<Q.ttl).map(([Q])=>Q);return{size:I.length,txIds:I,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(Q=>!Q.success).length/B.length,totalChecks:B.length}}getAverageResponseTime(A){const B=this.healthData.get(A);return!B||B.length===0?0:B.reduce((I,Q)=>I+Q.responseTime,0)/B.length}recordGatewayResponse(A,B,I){this.healthData.has(A)||this.healthData.set(A,[]);const Q=this.healthData.get(A);Q.push({responseTime:B,success:I,timestamp:Date.now()}),Q.length>this.MAX_HEALTH_RECORDS&&Q.shift()}reportFetchTiming(A,B,I){this.recordGatewayResponse(A,B,I),this.logger.debug("Fetch timing reported",{host:A,timingMs:B,success:I})}getGatewayHealth(A){const B=this.gateways.find(s=>s.host===A);if(!B)return;const I=this.healthData.get(A)||[],Q=this.originalPriorities.get(A)??B.priority;if(I.length===0)return{host:A,priority:B.priority,originalPriority:Q,successCount:0,failureCount:0,totalChecks:0,successRate:0,averageResponseTime:0,lastSuccess:null,lastFailure:null,isHealthy:!0};const E=I.filter(s=>s.success).length,i=I.filter(s=>!s.success).length,e=E/I.length,a=Math.round(I.reduce((s,n)=>s+n.responseTime,0)/I.length),C=I.filter(s=>s.success).pop()?.timestamp??null,o=I.filter(s=>!s.success).pop()?.timestamp??null,t=e>=.5;return{host:A,priority:B.priority,originalPriority:Q,successCount:E,failureCount:i,totalChecks:I.length,successRate:e,averageResponseTime:a,lastSuccess:C,lastFailure:o,isHealthy:t}}getAllGatewayHealth(){return this.gateways.map(A=>this.getGatewayHealth(A.host))}adjustGatewayPriorities(A){const B=A?.minChecks??3,I=A?.healthyThreshold??.5,E=this.getAllGatewayHealth().reduce((C,o)=>C+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((C,o)=>({gateway:C,originalIndex:o}));i.sort((C,o)=>{const t=this.getGatewayHealth(C.gateway.host),s=this.getGatewayHealth(o.gateway.host),n=t.successRate>=I||t.totalChecks===0,r=s.successRate>=I||s.totalChecks===0;if(n&&!r)return-1;if(!n&&r)return 1;if(t.totalChecks>0&&s.totalChecks>0){const c=t.averageResponseTime-s.averageResponseTime;if(Math.abs(c)>100)return c}if(t.totalChecks>0&&s.totalChecks>0){const c=s.successRate-t.successRate;if(Math.abs(c)>.1)return c}return C.originalIndex-o.originalIndex});const e=i.map(C=>C.gateway),a=Math.min(...Array.from(this.originalPriorities.values()));return e.forEach((C,o)=>{C.priority=a+o}),this.gateways=e,this.logger.info("Gateway priorities adjusted",{newOrder:this.gateways.map(C=>({host:C.host,priority:C.priority,health:this.getGatewayHealth(C.host)}))}),[...this.gateways]}async runHealthCheck(A){const B=Date.now(),I=A?.txId??"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk012345",Q=A?.healthyThreshold??.5;A?.fastThreshold,this.logger.info("Starting gateway health check",{txId:I,gateways:this.gateways.map(r=>r.host)});const E=this.gateways.map(async r=>{const c=Date.now();let G=!1,D=this.timeout;try{const h=VB(I,r),w=new AbortController,y=setTimeout(()=>w.abort(),this.timeout),R=await fetch(h,{method:"HEAD",mode:"cors",signal:w.signal});clearTimeout(y),D=Date.now()-c,G=R.ok||R.status>=200&&R.status<400}catch{D=Date.now()-c,G=!1}return this.recordGatewayResponse(r.host,D,G),{host:r.host,success:G,responseTime:D}}),i=await Promise.all(E),e=this.getAllGatewayHealth(),a=[],C=[];let o=null,t=1/0;for(const r of i){const c=e.find(G=>G.host===r.host);r.success&&r.responseTime<t&&(t=r.responseTime,o=r.host),(c.successRate>=Q||c.totalChecks===1)&&r.success?a.push(r.host):C.push(r.host)}const s=Date.now()-B;A?.adjustPriorities&&this.adjustGatewayPriorities({minChecks:A.minChecksForAdjustment??1,healthyThreshold:Q});const n={timestamp:B,gateways:e,healthyGateways:a,unhealthyGateways:C,fastestGateway:o,totalTime:s};return this.logger.info("Health check complete",{healthyGateways:a,unhealthyGateways:C,fastestGateway:o,totalTime:s}),n}resetGatewayPriorities(){this.gateways.forEach(A=>{const B=this.originalPriorities.get(A.host);B!==void 0&&(A.priority=B)}),this.gateways.sort((A,B)=>{const I=this.originalPriorities.get(A.host)??A.priority,Q=this.originalPriorities.get(B.host)??B.priority;return I-Q}),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 TA=new GD,Ni=["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"],hD="ipfs.io",Eo="/ipfs/";function lD(g){if(!g||typeof g!="string")return null;if(g.startsWith("ipfs://ipfs/"))return g.slice(12);if(g.startsWith("ipfs://"))return g.slice(7);try{const A=new URL(g),{hostname:B,pathname:I}=A,Q=B.match(/^([A-Za-z0-9]+)\.ipfs\.dweb\.link$/);if(Q)return`${Q[1]}${I}`;if(Ni.some(i=>B===i||B.endsWith("."+i))&&I.startsWith(Eo))return I.slice(Eo.length)}catch{}return null}function hZ(g){if(!g||typeof g!="string")return!1;if(g.startsWith("ipfs://"))return!0;try{const A=new URL(g),{hostname:B,pathname:I}=A;if(/^[A-Za-z0-9]+\.ipfs\.dweb\.link$/.test(B)||Ni.some(E=>B===E||B.endsWith("."+E))&&I.startsWith(Eo))return!0}catch{}return!1}function lZ(g){if(!(!g||g.startsWith("ipfs://")))try{const{hostname:A}=new URL(g);return Ni.some(I=>A===I||A.endsWith("."+I))?A:void 0}catch{return}}function DZ(g,A={}){if(!g)return g;const B=typeof A=="string"?{gatewayHost:A}:A,{gatewayHost:I=hD,preserveOriginalGateway:Q=!1}=B,E=lD(g);if(E){if(Q){const i=lZ(g);if(i)return`https://${i}/ipfs/${E}`}return`https://${I}/ipfs/${E}`}return g}function Wi(g){throw new Error('Could not dynamically require "'+g+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var io={exports:{}};var DD;function dZ(){return DD||(DD=1,(function(g,A){(function(B){g.exports=B()})(function(){return(function B(I,Q,E){function i(C,o){if(!Q[C]){if(!I[C]){var t=typeof Wi=="function"&&Wi;if(!o&&t)return t(C,!0);if(e)return e(C,!0);var s=new Error("Cannot find module '"+C+"'");throw s.code="MODULE_NOT_FOUND",s}var n=Q[C]={exports:{}};I[C][0].call(n.exports,function(r){var c=I[C][1][r];return i(c||r)},n,n.exports,B,I,Q,E)}return Q[C].exports}for(var e=typeof Wi=="function"&&Wi,a=0;a<E.length;a++)i(E[a]);return i})({1:[function(B,I,Q){(function(E){var i=E.MutationObserver||E.WebKitMutationObserver,e;if(i){var a=0,C=new i(r),o=E.document.createTextNode("");C.observe(o,{characterData:!0}),e=function(){o.data=a=++a%2}}else if(!E.setImmediate&&typeof E.MessageChannel<"u"){var t=new E.MessageChannel;t.port1.onmessage=r,e=function(){t.port2.postMessage(0)}}else"document"in E&&"onreadystatechange"in E.document.createElement("script")?e=function(){var G=E.document.createElement("script");G.onreadystatechange=function(){r(),G.onreadystatechange=null,G.parentNode.removeChild(G),G=null},E.document.documentElement.appendChild(G)}:e=function(){setTimeout(r,0)};var s,n=[];function r(){s=!0;for(var G,D,h=n.length;h;){for(D=n,n=[],G=-1;++G<h;)D[G]();h=n.length}s=!1}I.exports=c;function c(G){n.push(G)===1&&!s&&e()}}).call(this,typeof Ei<"u"?Ei:typeof self<"u"?self:typeof window<"u"?window:{})},{}],2:[function(B,I,Q){var E=B(1);function i(){}var e={},a=["REJECTED"],C=["FULFILLED"],o=["PENDING"];I.exports=t;function t(R){if(typeof R!="function")throw new TypeError("resolver must be a function");this.state=o,this.queue=[],this.outcome=void 0,R!==i&&c(this,R)}t.prototype.catch=function(R){return this.then(null,R)},t.prototype.then=function(R,Y){if(typeof R!="function"&&this.state===C||typeof Y!="function"&&this.state===a)return this;var k=new this.constructor(i);if(this.state!==o){var W=this.state===C?R:Y;n(k,W,this.outcome)}else this.queue.push(new s(k,R,Y));return k};function s(R,Y,k){this.promise=R,typeof Y=="function"&&(this.onFulfilled=Y,this.callFulfilled=this.otherCallFulfilled),typeof k=="function"&&(this.onRejected=k,this.callRejected=this.otherCallRejected)}s.prototype.callFulfilled=function(R){e.resolve(this.promise,R)},s.prototype.otherCallFulfilled=function(R){n(this.promise,this.onFulfilled,R)},s.prototype.callRejected=function(R){e.reject(this.promise,R)},s.prototype.otherCallRejected=function(R){n(this.promise,this.onRejected,R)};function n(R,Y,k){E(function(){var W;try{W=Y(k)}catch(j){return e.reject(R,j)}W===R?e.reject(R,new TypeError("Cannot resolve promise with itself")):e.resolve(R,W)})}e.resolve=function(R,Y){var k=G(r,Y);if(k.status==="error")return e.reject(R,k.value);var W=k.value;if(W)c(R,W);else{R.state=C,R.outcome=Y;for(var j=-1,X=R.queue.length;++j<X;)R.queue[j].callFulfilled(Y)}return R},e.reject=function(R,Y){R.state=a,R.outcome=Y;for(var k=-1,W=R.queue.length;++k<W;)R.queue[k].callRejected(Y);return R};function r(R){var Y=R&&R.then;if(R&&(typeof R=="object"||typeof R=="function")&&typeof Y=="function")return function(){Y.apply(R,arguments)}}function c(R,Y){var k=!1;function W(QA){k||(k=!0,e.reject(R,QA))}function j(QA){k||(k=!0,e.resolve(R,QA))}function X(){Y(j,W)}var z=G(X);z.status==="error"&&W(z.value)}function G(R,Y){var k={};try{k.value=R(Y),k.status="success"}catch(W){k.status="error",k.value=W}return k}t.resolve=D;function D(R){return R instanceof this?R:e.resolve(new this(i),R)}t.reject=h;function h(R){var Y=new this(i);return e.reject(Y,R)}t.all=w;function w(R){var Y=this;if(Object.prototype.toString.call(R)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=R.length,W=!1;if(!k)return this.resolve([]);for(var j=new Array(k),X=0,z=-1,QA=new this(i);++z<k;)CA(R[z],z);return QA;function CA(dA,uA){Y.resolve(dA).then(AA,function(EA){W||(W=!0,e.reject(QA,EA))});function AA(EA){j[uA]=EA,++X===k&&!W&&(W=!0,e.resolve(QA,j))}}}t.race=y;function y(R){var Y=this;if(Object.prototype.toString.call(R)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=R.length,W=!1;if(!k)return this.resolve([]);for(var j=-1,X=new this(i);++j<k;)z(R[j]);return X;function z(QA){Y.resolve(QA).then(function(CA){W||(W=!0,e.resolve(X,CA))},function(CA){W||(W=!0,e.reject(X,CA))})}}},{1:1}],3:[function(B,I,Q){(function(E){typeof E.Promise!="function"&&(E.Promise=B(2))}).call(this,typeof Ei<"u"?Ei:typeof self<"u"?self:typeof window<"u"?window:{})},{2:2}],4:[function(B,I,Q){var E=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(F){return typeof F}:function(F){return F&&typeof Symbol=="function"&&F.constructor===Symbol&&F!==Symbol.prototype?"symbol":typeof F};function i(F,S){if(!(F instanceof S))throw new TypeError("Cannot call a class as a function")}function e(){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=e();function C(){try{if(!a||!a.open)return!1;var F=typeof openDatabase<"u"&&/(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&!/BlackBerry/.test(navigator.platform),S=typeof fetch=="function"&&fetch.toString().indexOf("[native code")!==-1;return(!F||S)&&typeof indexedDB<"u"&&typeof IDBKeyRange<"u"}catch{return!1}}function o(F,S){F=F||[],S=S||{};try{return new Blob(F,S)}catch(p){if(p.name!=="TypeError")throw p;for(var u=typeof BlobBuilder<"u"?BlobBuilder:typeof MSBlobBuilder<"u"?MSBlobBuilder:typeof MozBlobBuilder<"u"?MozBlobBuilder:WebKitBlobBuilder,U=new u,f=0;f<F.length;f+=1)U.append(F[f]);return U.getBlob(S.type)}}typeof Promise>"u"&&B(3);var t=Promise;function s(F,S){S&&F.then(function(u){S(null,u)},function(u){S(u)})}function n(F,S,u){typeof S=="function"&&F.then(S),typeof u=="function"&&F.catch(u)}function r(F){return typeof F!="string"&&(console.warn(F+" used as a key, but it is not a string."),F=String(F)),F}function c(){if(arguments.length&&typeof arguments[arguments.length-1]=="function")return arguments[arguments.length-1]}var G="local-forage-detect-blob-support",D=void 0,h={},w=Object.prototype.toString,y="readonly",R="readwrite";function Y(F){for(var S=F.length,u=new ArrayBuffer(S),U=new Uint8Array(u),f=0;f<S;f++)U[f]=F.charCodeAt(f);return u}function k(F){return new t(function(S){var u=F.transaction(G,R),U=o([""]);u.objectStore(G).put(U,"key"),u.onabort=function(f){f.preventDefault(),f.stopPropagation(),S(!1)},u.oncomplete=function(){var f=navigator.userAgent.match(/Chrome\/(\d+)/),p=navigator.userAgent.match(/Edge\//);S(p||!f||parseInt(f[1],10)>=43)}}).catch(function(){return!1})}function W(F){return typeof D=="boolean"?t.resolve(D):k(F).then(function(S){return D=S,D})}function j(F){var S=h[F.name],u={};u.promise=new t(function(U,f){u.resolve=U,u.reject=f}),S.deferredOperations.push(u),S.dbReady?S.dbReady=S.dbReady.then(function(){return u.promise}):S.dbReady=u.promise}function X(F){var S=h[F.name],u=S.deferredOperations.pop();if(u)return u.resolve(),u.promise}function z(F,S){var u=h[F.name],U=u.deferredOperations.pop();if(U)return U.reject(S),U.promise}function QA(F,S){return new t(function(u,U){if(h[F.name]=h[F.name]||SA(),F.db)if(S)j(F),F.db.close();else return u(F.db);var f=[F.name];S&&f.push(F.version);var p=a.open.apply(a,f);S&&(p.onupgradeneeded=function(N){var H=p.result;try{H.createObjectStore(F.storeName),N.oldVersion<=1&&H.createObjectStore(G)}catch(x){if(x.name==="ConstraintError")console.warn('The database "'+F.name+'" has been upgraded from version '+N.oldVersion+" to version "+N.newVersion+', but the storage "'+F.storeName+'" already exists.');else throw x}}),p.onerror=function(N){N.preventDefault(),U(p.error)},p.onsuccess=function(){var N=p.result;N.onversionchange=function(H){H.target.close()},u(N),X(F)}})}function CA(F){return QA(F,!1)}function dA(F){return QA(F,!0)}function uA(F,S){if(!F.db)return!0;var u=!F.db.objectStoreNames.contains(F.storeName),U=F.version<F.db.version,f=F.version>F.db.version;if(U&&(F.version!==S&&console.warn('The database "'+F.name+`" can't be downgraded from version `+F.db.version+" to version "+F.version+"."),F.version=F.db.version),f||u){if(u){var p=F.db.version+1;p>F.version&&(F.version=p)}return!0}return!1}function AA(F){return new t(function(S,u){var U=new FileReader;U.onerror=u,U.onloadend=function(f){var p=btoa(f.target.result||"");S({__local_forage_encoded_blob:!0,data:p,type:F.type})},U.readAsBinaryString(F)})}function EA(F){var S=Y(atob(F.data));return o([S],{type:F.type})}function ZA(F){return F&&F.__local_forage_encoded_blob}function NA(F){var S=this,u=S._initReady().then(function(){var U=h[S._dbInfo.name];if(U&&U.dbReady)return U.dbReady});return n(u,F,F),u}function Pa(F){j(F);for(var S=h[F.name],u=S.forages,U=0;U<u.length;U++){var f=u[U];f._dbInfo.db&&(f._dbInfo.db.close(),f._dbInfo.db=null)}return F.db=null,CA(F).then(function(p){return F.db=p,uA(F)?dA(F):p}).then(function(p){F.db=S.db=p;for(var N=0;N<u.length;N++)u[N]._dbInfo.db=p}).catch(function(p){throw z(F,p),p})}function aA(F,S,u,U){U===void 0&&(U=1);try{var f=F.db.transaction(F.storeName,S);u(null,f)}catch(p){if(U>0&&(!F.db||p.name==="InvalidStateError"||p.name==="NotFoundError"))return t.resolve().then(function(){if(!F.db||p.name==="NotFoundError"&&!F.db.objectStoreNames.contains(F.storeName)&&F.version<=F.db.version)return F.db&&(F.version=F.db.version+1),dA(F)}).then(function(){return Pa(F).then(function(){aA(F,S,u,U-1)})}).catch(u);u(p)}}function SA(){return{forages:[],db:null,dbReady:null,deferredOperations:[]}}function uI(F){var S=this,u={db:null};if(F)for(var U in F)u[U]=F[U];var f=h[u.name];f||(f=SA(),h[u.name]=f),f.forages.push(S),S._initReady||(S._initReady=S.ready,S.ready=NA);var p=[];function N(){return t.resolve()}for(var H=0;H<f.forages.length;H++){var x=f.forages[H];x!==S&&p.push(x._initReady().catch(N))}var q=f.forages.slice(0);return t.all(p).then(function(){return u.db=f.db,CA(u)}).then(function(V){return u.db=V,uA(u,S._defaultConfig.version)?dA(u):V}).then(function(V){u.db=f.db=V,S._dbInfo=u;for(var $=0;$<q.length;$++){var oA=q[$];oA!==S&&(oA._dbInfo.db=u.db,oA._dbInfo.version=u.version)}})}function kG(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){aA(u._dbInfo,y,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=x.get(F);q.onsuccess=function(){var V=q.result;V===void 0&&(V=null),ZA(V)&&(V=EA(V)),f(V)},q.onerror=function(){p(q.error)}}catch(V){p(V)}})}).catch(p)});return s(U,S),U}function yb(F,S){var u=this,U=new t(function(f,p){u.ready().then(function(){aA(u._dbInfo,y,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=x.openCursor(),V=1;q.onsuccess=function(){var $=q.result;if($){var oA=$.value;ZA(oA)&&(oA=EA(oA));var hA=F(oA,$.key,V++);hA!==void 0?f(hA):$.continue()}else f()},q.onerror=function(){p(q.error)}}catch($){p($)}})}).catch(p)});return s(U,S),U}function A4(F,S,u){var U=this;F=r(F);var f=new t(function(p,N){var H;U.ready().then(function(){return H=U._dbInfo,w.call(S)==="[object Blob]"?W(H.db).then(function(x){return x?S:AA(S)}):S}).then(function(x){aA(U._dbInfo,R,function(q,V){if(q)return N(q);try{var $=V.objectStore(U._dbInfo.storeName);x===null&&(x=void 0);var oA=$.put(x,F);V.oncomplete=function(){x===void 0&&(x=null),p(x)},V.onabort=V.onerror=function(){var hA=oA.error?oA.error:oA.transaction.error;N(hA)}}catch(hA){N(hA)}})}).catch(N)});return s(f,u),f}function B4(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){aA(u._dbInfo,R,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=x.delete(F);H.oncomplete=function(){f()},H.onerror=function(){p(q.error)},H.onabort=function(){var V=q.error?q.error:q.transaction.error;p(V)}}catch(V){p(V)}})}).catch(p)});return s(U,S),U}function g4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){aA(S._dbInfo,R,function(p,N){if(p)return f(p);try{var H=N.objectStore(S._dbInfo.storeName),x=H.clear();N.oncomplete=function(){U()},N.onabort=N.onerror=function(){var q=x.error?x.error:x.transaction.error;f(q)}}catch(q){f(q)}})}).catch(f)});return s(u,F),u}function I4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){aA(S._dbInfo,y,function(p,N){if(p)return f(p);try{var H=N.objectStore(S._dbInfo.storeName),x=H.count();x.onsuccess=function(){U(x.result)},x.onerror=function(){f(x.error)}}catch(q){f(q)}})}).catch(f)});return s(u,F),u}function Q4(F,S){var u=this,U=new t(function(f,p){if(F<0){f(null);return}u.ready().then(function(){aA(u._dbInfo,y,function(N,H){if(N)return p(N);try{var x=H.objectStore(u._dbInfo.storeName),q=!1,V=x.openKeyCursor();V.onsuccess=function(){var $=V.result;if(!$){f(null);return}F===0||q?f($.key):(q=!0,$.advance(F))},V.onerror=function(){p(V.error)}}catch($){p($)}})}).catch(p)});return s(U,S),U}function E4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){aA(S._dbInfo,y,function(p,N){if(p)return f(p);try{var H=N.objectStore(S._dbInfo.storeName),x=H.openKeyCursor(),q=[];x.onsuccess=function(){var V=x.result;if(!V){U(q);return}q.push(V.key),V.continue()},x.onerror=function(){f(x.error)}}catch(V){f(V)}})}).catch(f)});return s(u,F),u}function i4(F,S){S=c.apply(this,arguments);var u=this.config();F=typeof F!="function"&&F||{},F.name||(F.name=F.name||u.name,F.storeName=F.storeName||u.storeName);var U=this,f;if(!F.name)f=t.reject("Invalid arguments");else{var p=F.name===u.name&&U._dbInfo.db,N=p?t.resolve(U._dbInfo.db):CA(F).then(function(H){var x=h[F.name],q=x.forages;x.db=H;for(var V=0;V<q.length;V++)q[V]._dbInfo.db=H;return H});F.storeName?f=N.then(function(H){if(H.objectStoreNames.contains(F.storeName)){var x=H.version+1;j(F);var q=h[F.name],V=q.forages;H.close();for(var $=0;$<V.length;$++){var oA=V[$];oA._dbInfo.db=null,oA._dbInfo.version=x}var hA=new t(function(DA,LA){var WA=a.open(F.name,x);WA.onerror=function(xB){var PE=WA.result;PE.close(),LA(xB)},WA.onupgradeneeded=function(){var xB=WA.result;xB.deleteObjectStore(F.storeName)},WA.onsuccess=function(){var xB=WA.result;xB.close(),DA(xB)}});return hA.then(function(DA){q.db=DA;for(var LA=0;LA<V.length;LA++){var WA=V[LA];WA._dbInfo.db=DA,X(WA._dbInfo)}}).catch(function(DA){throw(z(F,DA)||t.resolve()).catch(function(){}),DA})}}):f=N.then(function(H){j(F);var x=h[F.name],q=x.forages;H.close();for(var V=0;V<q.length;V++){var $=q[V];$._dbInfo.db=null}var oA=new t(function(hA,DA){var LA=a.deleteDatabase(F.name);LA.onerror=function(){var WA=LA.result;WA&&WA.close(),DA(LA.error)},LA.onblocked=function(){console.warn('dropInstance blocked for database "'+F.name+'" until all open connections are closed')},LA.onsuccess=function(){var WA=LA.result;WA&&WA.close(),hA(WA)}});return oA.then(function(hA){x.db=hA;for(var DA=0;DA<q.length;DA++){var LA=q[DA];X(LA._dbInfo)}}).catch(function(hA){throw(z(F,hA)||t.resolve()).catch(function(){}),hA})})}return s(f,S),f}var e4={_driver:"asyncStorage",_initStorage:uI,_support:C(),iterate:yb,getItem:kG,setItem:A4,removeItem:B4,clear:g4,length:I4,key:Q4,keys:E4,dropInstance:i4};function a4(){return typeof openDatabase=="function"}var Tg="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",C4="~~local_forage_type~",ub=/^~~local_forage_type~([^~]+)~/,_a="__lfsc__:",ZG=_a.length,NG="arbf",WG="blob",mb="si08",Sb="ui08",bb="uic8",pb="si16",Yb="si32",Ub="ur16",fb="ui32",kb="fl32",Zb="fl64",Nb=ZG+NG.length,Wb=Object.prototype.toString;function Hb(F){var S=F.length*.75,u=F.length,U,f=0,p,N,H,x;F[F.length-1]==="="&&(S--,F[F.length-2]==="="&&S--);var q=new ArrayBuffer(S),V=new Uint8Array(q);for(U=0;U<u;U+=4)p=Tg.indexOf(F[U]),N=Tg.indexOf(F[U+1]),H=Tg.indexOf(F[U+2]),x=Tg.indexOf(F[U+3]),V[f++]=p<<2|N>>4,V[f++]=(N&15)<<4|H>>2,V[f++]=(H&3)<<6|x&63;return q}function HG(F){var S=new Uint8Array(F),u="",U;for(U=0;U<S.length;U+=3)u+=Tg[S[U]>>2],u+=Tg[(S[U]&3)<<4|S[U+1]>>4],u+=Tg[(S[U+1]&15)<<2|S[U+2]>>6],u+=Tg[S[U+2]&63];return S.length%3===2?u=u.substring(0,u.length-1)+"=":S.length%3===1&&(u=u.substring(0,u.length-2)+"=="),u}function o4(F,S){var u="";if(F&&(u=Wb.call(F)),F&&(u==="[object ArrayBuffer]"||F.buffer&&Wb.call(F.buffer)==="[object ArrayBuffer]")){var U,f=_a;F instanceof ArrayBuffer?(U=F,f+=NG):(U=F.buffer,u==="[object Int8Array]"?f+=mb:u==="[object Uint8Array]"?f+=Sb:u==="[object Uint8ClampedArray]"?f+=bb:u==="[object Int16Array]"?f+=pb:u==="[object Uint16Array]"?f+=Ub:u==="[object Int32Array]"?f+=Yb:u==="[object Uint32Array]"?f+=fb:u==="[object Float32Array]"?f+=kb:u==="[object Float64Array]"?f+=Zb:S(new Error("Failed to get type for BinaryArray"))),S(f+HG(U))}else if(u==="[object Blob]"){var p=new FileReader;p.onload=function(){var N=C4+F.type+"~"+HG(this.result);S(_a+WG+N)},p.readAsArrayBuffer(F)}else try{S(JSON.stringify(F))}catch(N){console.error("Couldn't convert value into a JSON string: ",F),S(null,N)}}function t4(F){if(F.substring(0,ZG)!==_a)return JSON.parse(F);var S=F.substring(Nb),u=F.substring(ZG,Nb),U;if(u===WG&&ub.test(S)){var f=S.match(ub);U=f[1],S=S.substring(f[0].length)}var p=Hb(S);switch(u){case NG:return p;case WG:return o([p],{type:U});case mb:return new Int8Array(p);case Sb:return new Uint8Array(p);case bb:return new Uint8ClampedArray(p);case pb:return new Int16Array(p);case Ub:return new Uint16Array(p);case Yb:return new Int32Array(p);case fb:return new Uint32Array(p);case kb:return new Float32Array(p);case Zb:return new Float64Array(p);default:throw new Error("Unkown type: "+u)}}var JG={serialize:o4,deserialize:t4,stringToBuffer:Hb,bufferToString:HG};function Jb(F,S,u,U){F.executeSql("CREATE TABLE IF NOT EXISTS "+S.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],u,U)}function s4(F){var S=this,u={db:null};if(F)for(var U in F)u[U]=typeof F[U]!="string"?F[U].toString():F[U];var f=new t(function(p,N){try{u.db=openDatabase(u.name,String(u.version),u.description,u.size)}catch(H){return N(H)}u.db.transaction(function(H){Jb(H,u,function(){S._dbInfo=u,p()},function(x,q){N(q)})},N)});return u.serializer=JG,f}function Og(F,S,u,U,f,p){F.executeSql(u,U,f,function(N,H){H.code===H.SYNTAX_ERR?N.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?",[S.storeName],function(x,q){q.rows.length?p(x,H):Jb(x,S,function(){x.executeSql(u,U,f,p)},p)},p):p(N,H)},p)}function n4(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"SELECT * FROM "+N.storeName+" WHERE key = ? LIMIT 1",[F],function(x,q){var V=q.rows.length?q.rows.item(0).value:null;V&&(V=N.serializer.deserialize(V)),f(V)},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function r4(F,S){var u=this,U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"SELECT * FROM "+N.storeName,[],function(x,q){for(var V=q.rows,$=V.length,oA=0;oA<$;oA++){var hA=V.item(oA),DA=hA.value;if(DA&&(DA=N.serializer.deserialize(DA)),DA=F(DA,hA.key,oA+1),DA!==void 0){f(DA);return}}f()},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function xb(F,S,u,U){var f=this;F=r(F);var p=new t(function(N,H){f.ready().then(function(){S===void 0&&(S=null);var x=S,q=f._dbInfo;q.serializer.serialize(S,function(V,$){$?H($):q.db.transaction(function(oA){Og(oA,q,"INSERT OR REPLACE INTO "+q.storeName+" (key, value) VALUES (?, ?)",[F,V],function(){N(x)},function(hA,DA){H(DA)})},function(oA){if(oA.code===oA.QUOTA_ERR){if(U>0){N(xb.apply(f,[F,x,u,U-1]));return}H(oA)}})})}).catch(H)});return s(p,u),p}function c4(F,S,u){return xb.apply(this,[F,S,u,1])}function G4(F,S){var u=this;F=r(F);var U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"DELETE FROM "+N.storeName+" WHERE key = ?",[F],function(){f()},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function h4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){var p=S._dbInfo;p.db.transaction(function(N){Og(N,p,"DELETE FROM "+p.storeName,[],function(){U()},function(H,x){f(x)})})}).catch(f)});return s(u,F),u}function l4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){var p=S._dbInfo;p.db.transaction(function(N){Og(N,p,"SELECT COUNT(key) as c FROM "+p.storeName,[],function(H,x){var q=x.rows.item(0).c;U(q)},function(H,x){f(x)})})}).catch(f)});return s(u,F),u}function D4(F,S){var u=this,U=new t(function(f,p){u.ready().then(function(){var N=u._dbInfo;N.db.transaction(function(H){Og(H,N,"SELECT key FROM "+N.storeName+" WHERE id = ? LIMIT 1",[F+1],function(x,q){var V=q.rows.length?q.rows.item(0).key:null;f(V)},function(x,q){p(q)})})}).catch(p)});return s(U,S),U}function d4(F){var S=this,u=new t(function(U,f){S.ready().then(function(){var p=S._dbInfo;p.db.transaction(function(N){Og(N,p,"SELECT key FROM "+p.storeName,[],function(H,x){for(var q=[],V=0;V<x.rows.length;V++)q.push(x.rows.item(V).key);U(q)},function(H,x){f(x)})})}).catch(f)});return s(u,F),u}function w4(F){return new t(function(S,u){F.transaction(function(U){U.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'",[],function(f,p){for(var N=[],H=0;H<p.rows.length;H++)N.push(p.rows.item(H).name);S({db:F,storeNames:N})},function(f,p){u(p)})},function(U){u(U)})})}function F4(F,S){S=c.apply(this,arguments);var u=this.config();F=typeof F!="function"&&F||{},F.name||(F.name=F.name||u.name,F.storeName=F.storeName||u.storeName);var U=this,f;return F.name?f=new t(function(p){var N;F.name===u.name?N=U._dbInfo.db:N=openDatabase(F.name,"","",0),F.storeName?p({db:N,storeNames:[F.storeName]}):p(w4(N))}).then(function(p){return new t(function(N,H){p.db.transaction(function(x){function q(hA){return new t(function(DA,LA){x.executeSql("DROP TABLE IF EXISTS "+hA,[],function(){DA()},function(WA,xB){LA(xB)})})}for(var V=[],$=0,oA=p.storeNames.length;$<oA;$++)V.push(q(p.storeNames[$]));t.all(V).then(function(){N()}).catch(function(hA){H(hA)})},function(x){H(x)})})}):f=t.reject("Invalid arguments"),s(f,S),f}var M4={_driver:"webSQLStorage",_initStorage:s4,_support:a4(),iterate:r4,getItem:n4,setItem:c4,removeItem:G4,clear:h4,length:l4,key:D4,keys:d4,dropInstance:F4};function R4(){try{return typeof localStorage<"u"&&"setItem"in localStorage&&!!localStorage.setItem}catch{return!1}}function qb(F,S){var u=F.name+"/";return F.storeName!==S.storeName&&(u+=F.storeName+"/"),u}function y4(){var F="_localforage_support_test";try{return localStorage.setItem(F,!0),localStorage.removeItem(F),!1}catch{return!0}}function u4(){return!y4()||localStorage.length>0}function m4(F){var S=this,u={};if(F)for(var U in F)u[U]=F[U];return u.keyPrefix=qb(F,S._defaultConfig),u4()?(S._dbInfo=u,u.serializer=JG,t.resolve()):t.reject()}function S4(F){var S=this,u=S.ready().then(function(){for(var U=S._dbInfo.keyPrefix,f=localStorage.length-1;f>=0;f--){var p=localStorage.key(f);p.indexOf(U)===0&&localStorage.removeItem(p)}});return s(u,F),u}function b4(F,S){var u=this;F=r(F);var U=u.ready().then(function(){var f=u._dbInfo,p=localStorage.getItem(f.keyPrefix+F);return p&&(p=f.serializer.deserialize(p)),p});return s(U,S),U}function p4(F,S){var u=this,U=u.ready().then(function(){for(var f=u._dbInfo,p=f.keyPrefix,N=p.length,H=localStorage.length,x=1,q=0;q<H;q++){var V=localStorage.key(q);if(V.indexOf(p)===0){var $=localStorage.getItem(V);if($&&($=f.serializer.deserialize($)),$=F($,V.substring(N),x++),$!==void 0)return $}}});return s(U,S),U}function Y4(F,S){var u=this,U=u.ready().then(function(){var f=u._dbInfo,p;try{p=localStorage.key(F)}catch{p=null}return p&&(p=p.substring(f.keyPrefix.length)),p});return s(U,S),U}function U4(F){var S=this,u=S.ready().then(function(){for(var U=S._dbInfo,f=localStorage.length,p=[],N=0;N<f;N++){var H=localStorage.key(N);H.indexOf(U.keyPrefix)===0&&p.push(H.substring(U.keyPrefix.length))}return p});return s(u,F),u}function f4(F){var S=this,u=S.keys().then(function(U){return U.length});return s(u,F),u}function k4(F,S){var u=this;F=r(F);var U=u.ready().then(function(){var f=u._dbInfo;localStorage.removeItem(f.keyPrefix+F)});return s(U,S),U}function Z4(F,S,u){var U=this;F=r(F);var f=U.ready().then(function(){S===void 0&&(S=null);var p=S;return new t(function(N,H){var x=U._dbInfo;x.serializer.serialize(S,function(q,V){if(V)H(V);else try{localStorage.setItem(x.keyPrefix+F,q),N(p)}catch($){($.name==="QuotaExceededError"||$.name==="NS_ERROR_DOM_QUOTA_REACHED")&&H($),H($)}})})});return s(f,u),f}function N4(F,S){if(S=c.apply(this,arguments),F=typeof F!="function"&&F||{},!F.name){var u=this.config();F.name=F.name||u.name,F.storeName=F.storeName||u.storeName}var U=this,f;return F.name?f=new t(function(p){F.storeName?p(qb(F,U._defaultConfig)):p(F.name+"/")}).then(function(p){for(var N=localStorage.length-1;N>=0;N--){var H=localStorage.key(N);H.indexOf(p)===0&&localStorage.removeItem(H)}}):f=t.reject("Invalid arguments"),s(f,S),f}var W4={_driver:"localStorageWrapper",_initStorage:m4,_support:R4(),iterate:p4,getItem:b4,setItem:Z4,removeItem:k4,clear:S4,length:f4,key:Y4,keys:U4,dropInstance:N4},H4=function(S,u){return S===u||typeof S=="number"&&typeof u=="number"&&isNaN(S)&&isNaN(u)},J4=function(S,u){for(var U=S.length,f=0;f<U;){if(H4(S[f],u))return!0;f++}return!1},Lb=Array.isArray||function(F){return Object.prototype.toString.call(F)==="[object Array]"},jE={},Vb={},YQ={INDEXEDDB:e4,WEBSQL:M4,LOCALSTORAGE:W4},x4=[YQ.INDEXEDDB._driver,YQ.WEBSQL._driver,YQ.LOCALSTORAGE._driver],$a=["dropInstance"],xG=["clear","getItem","iterate","key","keys","length","removeItem","setItem"].concat($a),q4={description:"",driver:x4.slice(),name:"localforage",size:4980736,storeName:"keyvaluepairs",version:1};function L4(F,S){F[S]=function(){var u=arguments;return F.ready().then(function(){return F[S].apply(F,u)})}}function qG(){for(var F=1;F<arguments.length;F++){var S=arguments[F];if(S)for(var u in S)S.hasOwnProperty(u)&&(Lb(S[u])?arguments[0][u]=S[u].slice():arguments[0][u]=S[u])}return arguments[0]}var V4=(function(){function F(S){i(this,F);for(var u in YQ)if(YQ.hasOwnProperty(u)){var U=YQ[u],f=U._driver;this[u]=f,jE[f]||this.defineDriver(U)}this._defaultConfig=qG({},q4),this._config=qG({},this._defaultConfig,S),this._driverSet=null,this._initDriver=null,this._ready=!1,this._dbInfo=null,this._wrapLibraryMethodsWithReady(),this.setDriver(this._config.driver).catch(function(){})}return F.prototype.config=function(u){if((typeof u>"u"?"undefined":E(u))==="object"){if(this._ready)return new Error("Can't call config() after localforage has been used.");for(var U in u){if(U==="storeName"&&(u[U]=u[U].replace(/\W/g,"_")),U==="version"&&typeof u[U]!="number")return new Error("Database version must be a number.");this._config[U]=u[U]}return"driver"in u&&u.driver?this.setDriver(this._config.driver):!0}else return typeof u=="string"?this._config[u]:this._config},F.prototype.defineDriver=function(u,U,f){var p=new t(function(N,H){try{var x=u._driver,q=new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver");if(!u._driver){H(q);return}for(var V=xG.concat("_initStorage"),$=0,oA=V.length;$<oA;$++){var hA=V[$],DA=!J4($a,hA);if((DA||u[hA])&&typeof u[hA]!="function"){H(q);return}}var LA=function(){for(var PE=function(K4){return function(){var z4=new Error("Method "+K4+" is not implemented by the current driver"),vb=t.reject(z4);return s(vb,arguments[arguments.length-1]),vb}},LG=0,X4=$a.length;LG<X4;LG++){var VG=$a[LG];u[VG]||(u[VG]=PE(VG))}};LA();var WA=function(PE){jE[x]&&console.info("Redefining LocalForage driver: "+x),jE[x]=u,Vb[x]=PE,N()};"_support"in u?u._support&&typeof u._support=="function"?u._support().then(WA,H):WA(!!u._support):WA(!0)}catch(xB){H(xB)}});return n(p,U,f),p},F.prototype.driver=function(){return this._driver||null},F.prototype.getDriver=function(u,U,f){var p=jE[u]?t.resolve(jE[u]):t.reject(new Error("Driver not found."));return n(p,U,f),p},F.prototype.getSerializer=function(u){var U=t.resolve(JG);return n(U,u),U},F.prototype.ready=function(u){var U=this,f=U._driverSet.then(function(){return U._ready===null&&(U._ready=U._initDriver()),U._ready});return n(f,u,u),f},F.prototype.setDriver=function(u,U,f){var p=this;Lb(u)||(u=[u]);var N=this._getSupportedDrivers(u);function H(){p._config.driver=p.driver()}function x($){return p._extend($),H(),p._ready=p._initStorage(p._config),p._ready}function q($){return function(){var oA=0;function hA(){for(;oA<$.length;){var DA=$[oA];return oA++,p._dbInfo=null,p._ready=null,p.getDriver(DA).then(x).catch(hA)}H();var LA=new Error("No available storage method found.");return p._driverSet=t.reject(LA),p._driverSet}return hA()}}var V=this._driverSet!==null?this._driverSet.catch(function(){return t.resolve()}):t.resolve();return this._driverSet=V.then(function(){var $=N[0];return p._dbInfo=null,p._ready=null,p.getDriver($).then(function(oA){p._driver=oA._driver,H(),p._wrapLibraryMethodsWithReady(),p._initDriver=q(N)})}).catch(function(){H();var $=new Error("No available storage method found.");return p._driverSet=t.reject($),p._driverSet}),n(this._driverSet,U,f),this._driverSet},F.prototype.supports=function(u){return!!Vb[u]},F.prototype._extend=function(u){qG(this,u)},F.prototype._getSupportedDrivers=function(u){for(var U=[],f=0,p=u.length;f<p;f++){var N=u[f];this.supports(N)&&U.push(N)}return U},F.prototype._wrapLibraryMethodsWithReady=function(){for(var u=0,U=xG.length;u<U;u++)L4(this,xG[u])},F.prototype.createInstance=function(u){return new F(u)},F})(),v4=new V4;I.exports=v4},{3:3}]},{},[4])(4)})})(io)),io.exports}var wZ=dZ();const FZ=dh(wZ);function JI(g){return`model:${g}`}function MZ(g){const A=g.lastIndexOf("/");return A>=0?g.substring(0,A+1):""}async function RZ(g,A=3,B=1e3){let I=null;for(let Q=0;Q<A;Q++)try{const E=await fetch(g);if(!E.ok)throw new Error(`HTTP ${E.status}: ${E.statusText}`);return E}catch(E){if(I=E,Q===A-1)throw E;const i=B*Math.pow(2,Q);console.warn(`[ModelCache] Fetch failed (attempt ${Q+1}/${A}), retrying in ${i}ms...`,{url:g,error:String(E)}),await new Promise(e=>setTimeout(e,i))}throw I}async function dD(g,A,B,I=3,Q=1e3){let E=null;for(let i=0;i<I;i++){const e=A?await A(g):g;try{const a=await fetch(e);if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);const C=await a.text(),o=JSON.parse(C),t=MZ(e),s={},n=[];if(o.weightsManifest&&Array.isArray(o.weightsManifest)){for(const c of o.weightsManifest)if(c.paths&&Array.isArray(c.paths))for(const G of c.paths)n.push(G)}const r=n.map(async c=>{const G=t+c,D=await RZ(G,I,Q);s[c]=await D.arrayBuffer()});return await Promise.all(r),{manifest:C,weights:s,savedAt:Date.now(),originalUrl:g}}catch(a){if(E=a,i===I-1)throw a;B?.(g);const C=Q*Math.pow(2,i);console.warn(`[ModelCache] Model fetch failed (attempt ${i+1}/${I}), re-resolving and retrying in ${C}ms...`,{url:g,resolvedUrl:e,error:String(a)}),await new Promise(o=>setTimeout(o,C))}}throw E}function eo(g,A){return JSON.parse(A.manifest),{load:async()=>wD(A)}}function wD(g){const A=JSON.parse(g.manifest),B=[],I=[];if(A.weightsManifest&&Array.isArray(A.weightsManifest))for(const Q of A.weightsManifest){if(Q.weights&&Array.isArray(Q.weights))for(const E of Q.weights)I.push(E);if(Q.paths&&Array.isArray(Q.paths))for(const E of Q.paths){const i=g.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:I.length>0?I:void 0,weightData:B.length>0?B.length===1?B[0]:B:void 0}}const FD=new Map;let MD=!1;function yZ(){MD||(MD=!0,import("@tensorflow/tfjs").then(g=>{g.io.registerLoadRouter((A=>{if(typeof A=="string"&&A.startsWith("cached://")){const B=FD.get(A);if(B)return{load:async()=>{const I=await B.store.getItem(B.key);if(!I)throw new Error(`[ModelCache] Model not in cache: ${A}`);return wD(I)}}}return null}))}))}yZ();class RD{constructor(A={}){this.store=FZ.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(JI(A))!=null}async getCacheInfo(A){const B=await this.store.getItem(JI(A));if(!B)return{cached:!1};let I=B.manifest.length;for(const Q of Object.values(B.weights))I+=Q.byteLength;return{cached:!0,savedAt:B.savedAt,size:I}}async loadFromCache(A,B){const I=await this.store.getItem(JI(B));if(!I)throw new Error(`[ModelCache] Model not cached: ${B}`);return A.loadGraphModel(eo(A,I))}async getOrFetchGraphModel(A,B,I={}){const Q=JI(B);try{const i=await this.store.getItem(Q);if(i)return console.info(`[ModelCache] Loading model from cache: ${B}`),await A.loadGraphModel(eo(A,i))}catch(i){console.warn("[ModelCache] Cache load failed, clearing and re-fetching:",i),await this.store.removeItem(Q)}console.info(`[ModelCache] Downloading model: ${B}`);const E=await dD(B,I.resolveUrl,I.invalidateUrlCache,I.maxRetries??3,I.baseDelayMs??1e3);return await this.store.setItem(Q,E),console.info(`[ModelCache] Model cached: ${B} (${Object.keys(E.weights).length} shards)`),A.loadGraphModel(eo(A,E))}async getOrFetchEssentiaUrl(A,B={}){const I=JI(A),Q=`cached://${A}`;if(await this.store.getItem(I))console.info(`[ModelCache] Loading Essentia model from cache: ${A}`);else{console.info(`[ModelCache] Downloading model for Essentia: ${A}`);const i=await dD(A,B.resolveUrl,B.invalidateUrlCache,B.maxRetries??3,B.baseDelayMs??1e3);await this.store.setItem(I,i),console.info(`[ModelCache] Model cached: ${A} (${Object.keys(i.weights).length} shards)`)}return FD.set(Q,{store:this.store,key:I}),Q}async clear(A){A?(await this.store.removeItem(JI(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 I of Object.values(B.weights))A+=I.byteLength}}),A}}const xI=new RD;function uZ(g){if(!g||!g.metadata)return null;if(typeof g.metadata=="string")try{const A=JSON.parse(g.metadata);return typeof A=="object"&&A!==null&&!Array.isArray(A)?A:null}catch{return null}return typeof g.metadata=="object"&&!Array.isArray(g.metadata)?g.metadata:null}function yD(g){const A={stems:[],mixes:[],hasExtras:!1};if(!g)return A;const B=pZ(g),I=YZ(g),Q=typeof g.vrm=="string"?g.vrm:void 0,E=mZ(g.lyrics),i=uD(g.visualizer),e=uD(g.video),a=SZ(g.merch),C=bZ(g.credits),o=typeof g.midi=="string"?g.midi:void 0,t=typeof g.step_mania=="string"?g.step_mania:void 0,s=typeof g.clone_hero=="string"?g.clone_hero:void 0,n=typeof g.external_url=="string"?g.external_url:void 0;return{hasExtras:B.length>0||I.length>0||!!Q||!!E||!!i||!!e||!!a||!!C||!!o||!!t||!!s||!!n,...B.length>0?{stems:B}:{},...I.length>0?{mixes:I}:{},...Q?{vrm:Q}:{},...E?{lyrics:E}:{},...i?{visualizer:i}:{},...e?{video:e}:{},...a?{merch:a}:{},...C?{credits:C}:{},...o?{midi:o}:{},...t?{step_mania:t}:{},...s?{clone_hero:s}:{},...n?{external_url:n}:{}}}function mZ(g){if(g){if(typeof g=="string")return{text:g};if(typeof g=="object"&&!Array.isArray(g)){const A=g;return{text:typeof A.text=="string"?A.text:void 0}}}}function uD(g){if(!g||typeof g!="object"||Array.isArray(g))return;const A=g;if(typeof A.uri=="string")return{uri:A.uri,mime_type:typeof A.mime_type=="string"?A.mime_type:void 0}}function SZ(g){if(!g||typeof g!="object"||Array.isArray(g))return;const A=g;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 bZ(g){if(!Array.isArray(g))return;const A=[];for(const B of g)if(B&&typeof B=="object"){const I=B;typeof I.name=="string"&&typeof I.credit=="string"&&A.push({name:I.name,credit:I.credit})}return A.length>0?A:void 0}function pZ(g){const A=g.stems;if(!Array.isArray(A))return[];const B=[];for(const I of A)if(I&&typeof I=="object"){const Q=I;B.push({name:typeof Q.name=="string"?Q.name:"",uri:typeof Q.uri=="string"?Q.uri:void 0,mime_type:typeof Q.mime_type=="string"?Q.mime_type:void 0})}return B}function YZ(g){const A=g.mixes;if(!Array.isArray(A))return[];const B=[];for(const I of A)if(I&&typeof I=="object"){const Q=I,E=UZ(Q.name),i=fZ(Q.conditions);B.push({name:E||"",uri:typeof Q.uri=="string"?Q.uri:void 0,mime_type:typeof Q.mime_type=="string"?Q.mime_type:void 0,conditions:i})}return B}function UZ(g){if(typeof g=="string")return g;if(g&&typeof g=="object"&&!Array.isArray(g)){const A=g;if(typeof A.value=="string")return A.value}return""}function fZ(g){if(!Array.isArray(g))return[];const A=[];for(const B of g)if(B&&typeof B=="object"){const I=B;typeof I.type=="string"&&typeof I.value=="string"&&A.push({type:I.type,value:I.value})}return A}function kZ(g,A){const B=[],I=new Date;for(const Q of g.mixes||[]){if(Q.conditions.length===0){B.push({mix:Q,conditions:[],allMet:!0,unmetConditions:[]});continue}const E=[],i=[];for(const e of Q.conditions){const a=ZZ(e,A,I);E.push(a),a.met||i.push(a)}B.push({mix:Q,conditions:E,allMet:i.length===0,unmetConditions:i})}return B}function ZZ(g,A,B=new Date){const{type:I,value:Q}=g,E=A?.environment,i=A?.appState;switch(I){case"weather":{const e=E?.weather?.weatherType||"",a=e.toLowerCase()===Q.toLowerCase();return{type:I,value:Q,met:a,reason:a?`Weather is ${e}`:`Weather is ${e} (need ${Q})`}}case"day":{const a=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][B.getDay()],C=a.toLowerCase()===Q.toLowerCase();return{type:I,value:Q,met:C,reason:C?`Today is ${a}`:`Today is ${a} (need ${Q})`}}case"start_time":{const e=B.getHours()*60+B.getMinutes(),a=mD(Q),C=e>=a;return{type:I,value:Q,met:C,reason:C?`Time is after ${Q}`:`Time is before ${Q}`}}case"end_time":{const e=B.getHours()*60+B.getMinutes(),a=mD(Q),C=e<a;return{type:I,value:Q,met:C,reason:C?`Time is before ${Q}`:`Time is after ${Q}`}}case"min_plays":{const e=parseInt(Q,10),a=i?.playCount??0,C=a>=e;return{type:I,value:Q,met:C,reason:C?`Played ${a} times (need ${e})`:`Played ${a} times (need ${e})`}}case"max_plays":{const e=parseInt(Q,10),a=i?.playCount??0,C=a<=e;return{type:I,value:Q,met:C,reason:C?`Played ${a} times (max ${e})`:`Played ${a} times (exceeds max ${e})`}}case"every_x_plays":{const e=parseInt(Q,10),a=i?.playCount??0,C=e>0&&a>0&&a%e===0;return{type:I,value:Q,met:C,reason:C?`Play #${a} (every ${e} plays)`:`Play #${a} (not a multiple of ${e})`}}case"altitude":{const e=E?.geolocation?.altitude;if(e==null)return{type:I,value:Q,met:!1,reason:"Altitude unavailable"};const a=NZ(Q),C=WZ(e,a.operator,a.threshold);return{type:I,value:Q,met:C,reason:C?`Altitude ${e}m ${a.operator} ${a.threshold}m`:`Altitude ${e}m (need ${a.operator} ${a.threshold}m)`}}case"favorite":{const e=i?.isFavorite??!1,a=Q.toLowerCase()==="true",C=e===a;return{type:I,value:Q,met:C,reason:C?e?"Track is favorited":"Track is not favorited":e?"Track is favorited (need unfavorited)":"Track is not favorited (need favorited)"}}case"birthday":{if(!i?.userBirthday)return{type:I,value:Q,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:I,value:Q,met:a,reason:a?"It's your birthday!":`Not your birthday (need ${i.userBirthday})`}}case"weight":return{type:I,value:Q,met:!0,reason:`Weight ${Q} (used for random selection, always available)`};default:return{type:I,value:Q,met:!0,reason:`Custom condition: ${I} = ${Q}`}}}function mD(g){const A=g.split(":");if(A.length!==2)return 0;const B=parseInt(A[0],10),I=parseInt(A[1],10);return isNaN(B)||isNaN(I)?0:B*60+I}function NZ(g){const A=g.match(/^(>=|<=|>|<|=)?\s*(\d+(?:\.\d+)?)\s*$/);return A?{operator:A[1]||">=",threshold:parseFloat(A[2])}:{operator:">=",threshold:parseFloat(g)||0}}function WZ(g,A,B){switch(A){case">":return g>B;case">=":return g>=B;case"<":return g<B;case"<=":return g<=B;case"=":case"==":return g===B;default:return g>=B}}class SD{generateName(A,B,I,Q,E=!1){const i=this.cleanTitle(B.title),e=E?A:`${A}-${Date.now()}-${Math.random()}`,a=new qB(e);switch(this.selectFormat(a)){case"class_title":return this.formatClassTitle(i,Q,a);case"adjective_construct":return this.formatAdjectiveConstruct(i,B.genre,I,a);case"clan_construct":return this.formatClanConstruct(i,B.artist,a);case"descriptive_epithet":return this.formatDescriptiveEpithet(i,Q,I,a);case"compound_adjective":return this.formatCompoundAdjective(i,B.genre,I,a);case"artist_inspired":return this.formatArtistInspired(i,B.artist,Q,a);case"mononym_subtitle":return this.formatMononymSubtitle(i,I,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,I){return`${A} the ${B}`}formatAdjectiveConstruct(A,B,I,Q){const E=this.findGenreKey(B),i=jB.adjectives[E]||jB.adjectives.default,e=this.calculateBalancedAdjectiveWeights(I),a=Q.weightedChoice(e),C=i[a];return`${Q.randomChoice(C)} ${A}`}formatClanConstruct(A,B,I){return`${A} of ${B}`}formatDescriptiveEpithet(A,B,I,Q){const E=Q.randomChoice(jB.descriptors),i=jB.classAspects[B]||["Wanderer","Seeker","Sage","Hero"],e=Q.randomChoice(i);return`${A}, the ${E} ${e}`}formatCompoundAdjective(A,B,I,Q){const E=Q.randomChoice(jB.prefixes),i=Q.randomChoice(jB.suffixes);return`${E}-${i} ${A}`}formatArtistInspired(A,B,I,Q){const E=B.split(" ")[0],i=Q.randomChoice(jB.occupations),e=`${E}${i}`,a=Q.randomChoice(jB.realms);return`${e} of the ${a}`}formatMononymSubtitle(A,B,I,Q){const E=A.split(" "),i=E[0];let e;return E.length>1?e=E.slice(1).join(" "):e=Q.randomChoice(jB.subtitlePrefixes),`${i} [${e}]`}calculateBalancedAdjectiveWeights(A){const I={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+I.bass],["treble",1+I.treble],["mid",1+I.mid],["quiet",1+I.quiet],["loud",1+I.loud]]}findGenreKey(A){const B=A.toLowerCase(),I=Object.keys(jB.adjectives).filter(Q=>Q!=="default"&&B.includes(Q));return I.length>0?I[0]:"default"}}class uB{static select(A,B,I,Q="relative"){if(A.length===0)throw new Error("Cannot select from empty items array");const E=this.getFinalWeights(A,B,Q),i=A.map(e=>{const a=this.getItemKey(e),C=a in E?E[a]:1;return[e,C]});return I.weightedChoice(i)}static selectMultiple(A,B,I,Q,E="relative"){if(A.length===0)return[];if(Q<=0)return[];if(Q>=A.length)return I.shuffle(A);const i=[],e=[...A],a={...B};for(let C=0;C<Q&&e.length>0;C++){const o=this.select(e,a,I,E);i.push(o);const t=e.indexOf(o);if(t!==-1){const s=this.getItemKey(o);e.splice(t,1),delete a[s]}}return i}static getProbabilities(A,B,I="relative"){if(A.length===0)return{};const Q=this.getFinalWeights(A,B,I),E=Object.values(Q).reduce((e,a)=>e+a,0);if(E===0){const e={};for(const a of A){const C=this.getItemKey(a);e[C]=1/A.length}return e}const i={};for(const e of A){const a=this.getItemKey(e),C=Q[a]||0;i[a]=E>0?C/E:0}return i}static normalizeWeights(A,B,I="relative"){if(A.length===0)return{};const Q=uB.getFinalWeights(A,B,I),E=Object.values(Q).reduce((e,a)=>e+a,0);if(E===0){const e={};for(const a of A){const C=uB.getItemKey(a);e[C]=1/A.length}return e}const i={};for(const e of A){const a=uB.getItemKey(e);i[a]=Q[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,I){const Q={};if(I==="default")for(const E of A){const i=this.getItemKey(E);Q[i]=1}else if(I==="absolute")for(const E of A){const i=this.getItemKey(E);Q[i]=B[i]!==void 0?B[i]:1}else for(const E of A){const i=this.getItemKey(E);Q[i]=B[i]!==void 0?B[i]:1}return Q}}const ao=[{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"]}],Co=[{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"]}],oo=[{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."}],HZ=["physical","exploration","combat","criminal","subterfuge","knowledge","magic","environmental","social","perception","practical","entertainment"],JZ={"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 to(){const g=IA.getInstance();for(const[A,B]of Object.entries(JZ))g.initializeDefaults(A,[...B])}function bD(){return IA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("appearance."))}function so(){bD()||to()}const xZ=Object.values(yC),qZ=Object.entries(ni).map(([g,A])=>({class:g,cantrips:A.cantrips,spells_by_level:A.spells_by_level}));function no(){const g=IA.getInstance();g.initializeDefaults("spells",xZ);for(const A of qZ){const B=`spells.${A.class}`;g.initializeDefaults(B,[A])}}function pD(){return IA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("spells"))}function Hi(){pD()||no()}const LZ=Object.values(mI).map(g=>({...g,source:"default",spawnWeight:g.spawnWeight??1,tags:g.tags??[]}));function ro(){IA.getInstance().initializeDefaults("equipment",LZ)}function YD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="equipment")}function co(){YD()||ro()}function Go(){IA.getInstance().initializeDefaults("races",[..._h])}function UD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="races")}function ho(){UD()||Go()}function lo(){IA.getInstance().initializeDefaults("races.data",[...Bl])}function fD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="races.data")}function kD(){fD()||lo()}function Do(){IA.getInstance().initializeDefaults("classes",[...jh])}function ZD(){return IA.getInstance().getRegisteredCategories().some(B=>B==="classes")}function wo(){ZD()||Do()}function VZ(){to(),no(),ro(),Go(),lo(),Do(),Fo(),Ro()}function vZ(){so(),Hi(),co(),ho(),kD(),wo(),Mo(),HD()}function Fo(){const g=IA.getInstance(),A={};for(const I of ao)A[I.class]||(A[I.class]=[]),A[I.class].push(I);g.initializeDefaults("classFeatures",[...ao]);for(const[I,Q]of Object.entries(A)){const E=`classFeatures.${I}`;g.initializeDefaults(E,Q)}const B={};for(const I of Co)B[I.race]||(B[I.race]=[]),B[I.race].push(I);g.initializeDefaults("racialTraits",[...Co]);for(const[I,Q]of Object.entries(B)){const E=`racialTraits.${I}`;g.initializeDefaults(E,Q)}}function ND(){return IA.getInstance().getRegisteredCategories().some(B=>B==="classFeatures"||B==="racialTraits")}function Mo(){ND()||Fo()}function Ro(){const g=IA.getInstance(),A={STR:[],DEX:[],CON:[],INT:[],WIS:[],CHA:[]};for(const B of oo)A[B.ability].push(B);g.initializeDefaults("skills",[...oo]);for(const[B,I]of Object.entries(A)){const Q=`skills.${B}`;g.initializeDefaults(Q,I)}}function WD(){const g=IA.getInstance();return g.hasCustomData("skills")||g.getDefaults("skills").length>0}function HD(){WD()||Ro()}class JD{static select(A){ho();const B=IA.getInstance(),I=B.get("races"),Q=B.getWeights("races"),E=B.getMode("races")||"default";return uB.select(I,Q,A,E)}}const UG=class UG{static suggest(A,B){wo();const I=IA.getInstance(),Q=I.get("classes"),E=this.calculateAllAffinities(A,Q),i=this.calculateProbabilities(E),e=I.getWeights("classes"),a=this.applyCustomWeights(i,e,Q),C=Object.entries(a).map(([o,t])=>[o,t]);return B.weightedChoice(C)}static calculateAllAffinities(A,B){const I={};for(const Q of B)I[Q]=this.calculateClassAffinity(A,Q);return I}static calculateClassAffinity(A,B){let I=this.getCustomClassAudioPreferences(B);if(I||(I=Ph[B]),!I)return .5;let Q=0;return Q+=this.getTraitContribution(A,I.primary,I,1),I.secondary&&(Q+=this.getTraitContribution(A,I.secondary,I,.5)),I.tertiary&&(Q+=this.getTraitContribution(A,I.tertiary,I,.25)),Q}static getCustomClassAudioPreferences(A){try{const I=IA.getInstance().get("classes.data");if(I&&Array.isArray(I)){const Q=I.find(E=>E.name===A);if(Q&&Q.audio_preferences)return Q.audio_preferences}}catch{}}static getTraitContribution(A,B,I,Q){switch(B){case"bass":return A.bass_dominance*(I.bass||1)*Q;case"treble":return A.treble_dominance*(I.treble||1)*Q;case"mid":return A.mid_dominance*(I.mid||1)*Q;case"amplitude":return A.average_amplitude*(I.amplitude||1)*Q;case"chaos":{const E=A.bass_dominance,i=A.treble_dominance,e=A.mid_dominance;return(1-(Math.max(E,i,e)-Math.min(E,i,e)))*Q}default:return 0}}static calculateProbabilities(A){const B=Object.keys(A),I=B.length;if(I===0)return{};const Q=Object.values(A).reduce((t,s)=>t+s,0);if(Q===0){const t=1/I,s={};for(const n of B)s[n]=t;return s}const E=this.BASELINE_PROBABILITY*I,i=1-E,e=E>=1?1/I:this.BASELINE_PROBABILITY,a=E>=1?0:i,C={};for(const t of B){const s=A[t]/Q;C[t]=e+s*a}const o=Object.values(C).reduce((t,s)=>t+s,0);for(const t of B)C[t]/=o;return C}static applyCustomWeights(A,B,I){if(Object.keys(B).length===0)return A;const Q=Object.values(B).reduce((a,C)=>a+Math.max(0,C),0);if(Q===0)return A;const E={};for(const[a,C]of Object.entries(B))I.includes(a)&&(E[a]=Math.max(0,C)/Q);const i=1-Object.values(E).reduce((a,C)=>a+C,0),e=Object.entries(A).filter(([a])=>!B[a]).reduce((a,[,C])=>a+C,0);for(const a of I)!B[a]&&A[a]&&(e>0?E[a]=A[a]/e*i:E[a]=i/I.length);return E}};UG.BASELINE_PROBABILITY=.04;let Ji=UG;class xi{static getSpicedValue(A,B,I){let Q;switch(A){case"bass":Q=I.rms_energy??I.dynamic_range??B;break;case"mid":I.spectral_centroid!==void 0?Q=Math.min(1,Math.max(0,(I.spectral_centroid-100)/9900)):Q=I.dynamic_range??B;break;case"treble":I.zero_crossing_rate!==void 0?Q=I.zero_crossing_rate:I.spectral_centroid!==void 0?Q=Math.min(1,Math.max(0,(I.spectral_centroid-100)/9900)):Q=B;break}return(B+Q)/2}static createFrequencyMappings(A){const B=["STR","DEX","CON","INT","WIS","CHA"],I=new Map,Q=A.shuffle(B),E=["bass","mid","treble"];for(let i=0;i<3;i++){const e=E[i],a=Q[i*2],C=Q[i*2+1],o=A.random()<.5;I.set(e,{abilities:[a,C],firstHasSpice:o})}return I}static calculateBaseScores(A,B){const{bass_dominance:I,mid_dominance:Q,treble_dominance:E}=A,i=this.createFrequencyMappings(B),e={STR:8,DEX:8,CON:8,INT:8,WIS:8,CHA:8},a=3.5,C=3.5;for(const[o,t]of i){const[s,n]=t.abilities,r=t.firstHasSpice;let c;switch(o){case"bass":c=I;break;case"mid":c=Q;break;case"treble":c=E;break}const G=r?this.getSpicedValue(o,c,A):c,D=r?c:this.getSpicedValue(o,c,A),h=B.random(),w=B.random();e[s]=Math.floor(8+h*C+G*a),e[n]=Math.floor(8+w*C+D*a)}return e}static applyRacialBonuses(A,B){const I=ri(B);if(!I)return console.warn(`Unknown race: "${B}", using no ability bonuses`),{...A};const Q=I.ability_bonuses,E={...A};if(Q)for(const[i,e]of Object.entries(Q)){const a=i;E[a]=Math.min(20,(E[a]||0)+(e||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 xD{static getSkillListDefinition(A){try{const I=IA.getInstance().get("skillLists");return Array.isArray(I)?I.find(Q=>Q.class===A):void 0}catch{return}}static assignSkills(A,B,I){const Q=CB.getInstance(),E=Q.getAllSkills(),i={};for(const s of E)i[s.id]="none";const e=mC(A);if(!e)return console.warn(`SkillAssigner: Unknown class "${A}", using default skill assignment`),i;const a=this.validateSkills(e.available_skills,Q),C=I?this.filterSkillsByPrerequisites(a,Q,I):a,o=this.getSkillListDefinition(A),t=this.selectSkills(C,e.skill_count,B,o?.selectionWeights);for(const s of t)i[s]="proficient";if(e.has_expertise&&e.expertise_count){const s=this.selectSkills(t,e.expertise_count,B);for(const n of s)i[n]="expertise"}return i}static validateSkills(A,B){const I=[];for(const Q of A)B.isValidSkill(Q)?I.push(Q):console.warn(`SkillAssigner: Invalid skill ID "${Q}" not found in SkillQuery. Skipping.`);return I}static filterSkillsByPrerequisites(A,B,I){const Q=[];for(const E of A){const i=B.getSkill(E);i&&(i.prerequisites&&!LB.validateSkillPrerequisites(i.prerequisites,I).valid||Q.push(E))}return Q}static selectSkills(A,B,I,Q){if(!Q||Q.mode==="default")return this.selectSkillsEqualWeight(A,B,I);const{weights:E,mode:i}=Q,e=[];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 n=0;n<s;n++)e.push(o)}}else{const n=Math.round((t??1)*10);for(let r=0;r<n;r++)e.push(o)}}if(e.length===0)return this.selectSkillsEqualWeight(A,B,I);for(let o=e.length-1;o>0;o--){const t=Math.floor(I.random()*(o+1));[e[o],e[t]]=[e[t],e[o]]}const a=[],C=new Set;for(const o of e)if(!C.has(o)&&(a.push(o),C.add(o),a.length>=B))break;return a}static selectSkillsEqualWeight(A,B,I){const Q=[...A];for(let E=Q.length-1;E>0;E--){const i=Math.floor(I.random()*(E+1));[Q[E],Q[i]]=[Q[i],Q[E]]}return Q.slice(0,B)}}const XZ=["Wizard","Sorcerer","Warlock","Bard","Cleric","Druid","Paladin"];class qD{static generate(A,B,I){so();const Q=new qB(A),E=IA.getInstance(),i=E.get("appearance.bodyTypes"),e=E.getWeights("appearance.bodyTypes"),a=E.getMode("appearance.bodyTypes")||"default",C=E.get("appearance.skinTones"),o=E.getWeights("appearance.skinTones"),t=E.getMode("appearance.skinTones")||"default",s=E.get("appearance.hairStyles"),n=E.getWeights("appearance.hairStyles"),r=E.getMode("appearance.hairStyles")||"default",c=E.get("appearance.hairColors"),G=E.getWeights("appearance.hairColors"),D=E.getMode("appearance.hairColors")||"default",h=E.get("appearance.eyeColors"),w=E.getWeights("appearance.eyeColors"),y=E.getMode("appearance.eyeColors")||"default",R=E.get("appearance.facialFeatures"),Y=E.getWeights("appearance.facialFeatures"),k=E.getMode("appearance.facialFeatures")||"default",W=uB.select(i,e,Q,a),j=uB.select(C,o,Q,t),X=uB.select(s,n,Q,r),z=uB.select(c,G,Q,D),QA=uB.select(h,w,Q,y),CA=Q.randomInt(1,4),dA=uB.selectMultiple(R,Y,Q,CA,k),uA=I.color_palette,AA=uA?.primary_color,EA=uA?.secondary_color,ZA=uA?.accent_color;let NA;return XZ.includes(B)&&(NA=this.generateAuraColor(B,uA?.primary_color)),{body_type:W,skin_tone:j,hair_style:X,hair_color:z,eye_color:QA,facial_features:dA,primary_color:AA,secondary_color:EA,accent_color:ZA,aura_color:NA}}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 I=A.replace("#",""),Q=parseInt(I.substring(0,2),16),E=parseInt(I.substring(2,4),16),i=parseInt(I.substring(4,6),16),e=Math.min(255,Math.floor(Q*B)),a=Math.min(255,Math.floor(E*B)),C=Math.min(255,Math.floor(i*B)),o=t=>t.toString(16).padStart(2,"0");return`#${o(e)}${o(a)}${o(C)}`}}class yo{static isSpellcaster(A){return["Bard","Cleric","Druid","Paladin","Ranger","Sorcerer","Warlock","Wizard"].includes(A)}static getSpellSlots(A,B){if(!this.isSpellcaster(A))return{};const I={};for(let E=0;E<=9;E++)I[E]={total:0,used:0};const Q=pC(A,B);if(!Q)return I;for(const[E,i]of Object.entries(Q)){const e=parseInt(E,10);I[e]={total:i,used:0}}return I}static getCantrips(A){if(!this.isSpellcaster(A))return[];Hi();const B=IA.getInstance(),I=bC(A),Q=I?[...I.cantrips]:[],E=`spells.${A}`,i=B.get(E);for(const e of i){const a=e;if(a.cantrips&&a.cantrips.length>0)for(const C of a.cantrips)Q.includes(C)||Q.push(C)}return Q}static getKnownSpells(A,B,I){if(!this.isSpellcaster(A))return[];Hi();const Q=IA.getInstance(),E=bC(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 e=`spells.${A}`,a=Q.get(e);for(const t of a){const s=t;if(s.cantrips&&s.cantrips.length>0)for(const n of s.cantrips);if(s.spells_by_level)for(const[n,r]of Object.entries(s.spells_by_level)){const c=Number(n);i[c]||(i[c]=[]);for(const G of r)i[c].includes(G)||i[c].push(G)}}const C={spells_by_level:i},o=[];for(let t=1;t<=B&&t<=9;t++){const s=C.spells_by_level[t];s&&s.length>0&&o.push(...s)}return I?this.filterSpellsByPrerequisites(o,I):o}static filterSpellsByPrerequisites(A,B){const I=[];for(const Q of A){const E=yC[Q];if(!E){I.push(Q);continue}E.prerequisites&&!eg.validateSpellPrerequisites(E.prerequisites,B).valid||I.push(Q)}return I}static initializeSpells(A,B,I){return{spell_slots:this.getSpellSlots(A,B),known_spells:this.getKnownSpells(A,B,I),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 I={...A},Q=I[B];return Q&&Q.used<Q.total&&(I[B]={...Q,used:Q.used+1}),I}static restoreSpellSlots(A,B){const I={...A};if(B!==void 0){const Q=I[B];Q&&(I[B]={...Q,used:0})}else for(let Q=1;Q<=9;Q++){const E=I[Q];E&&(I[Q]={...E,used:0})}return I}static filterCharacterSpells(A){if(!A.spells)return A;const B=this.filterSpellsByPrerequisites(A.spells.known_spells||[],A),I=this.filterSpellsByPrerequisites(A.spells.cantrips||[],A);return{...A,spells:{...A.spells,known_spells:B,cantrips:I}}}}const uo={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 LD(g){if(g in uo)return uo[g];try{const A=IA.getInstance(),B=`classStartingEquipment.${g}`,I=A.get(B);if(I&&Array.isArray(I)&&I.length>0){const Q=I[0];return{weapons:Q.weapons,armor:Q.armor,items:Q.items}}}catch{}}function mo(g,A,B){g.ability_scores[A]+=B;const I=g.ability_scores[A];g.ability_modifiers[A]=Math.floor((I-10)/2)}function So(g,A,B){const I=g.skills[A];if(!I||I==="none"){g.skills[A]=B;return}B==="expertise"&&(g.skills[A]=B)}class PA{static equipItem(A,B,I){const Q={applied:!1,count:0,errors:[]};if(A.equipment_effects||(A.equipment_effects=[]),this.findEquipmentEffect(A,B.name,I))return Q.applied=!0,Q;if(B.properties){const e=this.validateRequirements(A,B,B.properties);if(e.length>0)return Q.errors.push(...e),Q}const i={source:B.name,instanceId:I,effects:B.properties?[...B.properties]:[],features:[],skills:[],spells:[]};if(B.properties)for(const e of B.properties)try{this.applyProperty(A,e,B.name),Q.count++}catch(a){const C=a instanceof Error?a.message:String(a);Q.errors.push(`Failed to apply property from ${B.name}: ${C}`)}return B.grantsFeatures&&(this.applyEquipmentFeatures(A,B,I,i.features),Q.count+=i.features.length),B.grantsSkills&&(this.applyEquipmentSkills(A,B,I,i.skills),Q.count+=i.skills.length),B.grantsSpells&&(i.spells=B.grantsSpells.map(e=>({spellId:e.spellId,level:e.level,uses:e.uses,recharge:e.recharge})),this.addSpellsToCharacter(A,B.grantsSpells),Q.count+=i.spells.length),A.equipment_effects.push(i),Q.applied=Q.errors.length===0,Q}static unequipItem(A,B,I){const Q={applied:!1,count:0,errors:[]};if(!A.equipment_effects)return Q.errors.push("No equipment effects found on character"),Q;const E=A.equipment_effects.findIndex(e=>e.source===B&&e.instanceId===I);if(E===-1)return Q.errors.push(`Equipment "${B}" effects not found`),Q;const i=A.equipment_effects[E];return i.effects.length>0&&(this.removeProperties(A,i.effects),Q.count+=i.effects.length),i.features.length>0&&(this.removeEquipmentFeatures(A,B,I),Q.count+=i.features.length),i.skills.length>0&&(this.removeEquipmentSkills(A,i.skills),Q.count+=i.skills.length),i.spells&&i.spells.length>0&&(this.removeSpellsFromCharacter(A,i.spells),Q.count+=i.spells.length),A.equipment_effects.splice(E,1),Q.applied=Q.count>0,Q}static reapplyEquipmentEffects(A){const B={applied:!1,count:0,errors:[]};if(!A.equipment_effects||A.equipment_effects.length===0)return B;const I=[...A.equipment_effects];A.equipment_effects=[];for(const Q of I){const E={source:Q.source,instanceId:Q.instanceId,effects:[...Q.effects],features:[...Q.features],skills:[...Q.skills],spells:Q.spells?[...Q.spells]:[]};for(const i of Q.effects)try{this.applyProperty(A,i,Q.source),B.count++}catch(e){const a=e instanceof Error?e.message:String(e);B.errors.push(`Failed to reapply property from ${Q.source}: ${a}`)}for(const i of Q.features)this.addFeatureToCharacter(A,i),B.count++;for(const i of Q.skills)this.addSkillToCharacter(A,i),B.count++;Q.spells&&(this.addSpellsToCharacter(A,Q.spells),B.count+=Q.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 I of A.equipment_effects)B.push(...I.effects);return B}static evaluateACFormula(A,B){const I=A.trim();if(/^\d+$/.test(I))return parseInt(I,10);const Q=I.match(/^(\d+)\s*\+\s*min\(DEX,\s*(\d+)\)$/i);if(Q){const i=parseInt(Q[1],10),e=parseInt(Q[2],10);return i+Math.min(B,e)}const E=I.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,I){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,I);break;case"damage_bonus":this.trackDamageBonus(A,B,I);break;case"stat_requirement":this.trackStatRequirement(A,B,I);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 I=B.target,Q=B.value;if(bg(I)){mo(A,I,Q);return}}static applySkillProficiency(A,B){const I=B.target.toLowerCase(),Q=B.value;So(A,I,Q)}static applyAbilityUnlock(A,B){}static applyPassiveModifier(A,B){const I=B.target,Q=B.value;if(I==="speed"){A.speed+=Q;return}if(I==="ac"||I==="armor_class"){if(typeof Q=="string"){const E=A.ability_modifiers.DEX??0;A.armor_class=PA.evaluateACFormula(Q,E)}else A.armor_class+=Q;return}if(I==="max_hp"||I==="hp_max"){A.hp.max+=Q,A.hp.current+=Q;return}}static trackSpecialProperty(A,B,I){}static trackDamageBonus(A,B,I){}static removeProperties(A,B){for(let I=B.length-1;I>=0;I--){const Q=B[I];switch(Q.type){case"stat_bonus":this.removeStatBonus(A,Q);break;case"skill_proficiency":this.removeSkillProficiency(A,Q);break;case"passive_modifier":this.removePassiveModifier(A,Q);break}}}static removeStatBonus(A,B){const I=B.target,Q=B.value;bg(I)&&mo(A,I,-Q)}static removeSkillProficiency(A,B){const I=B.target.toLowerCase();A.skills[I]="none"}static removePassiveModifier(A,B){const I=B.target,Q=B.value;I==="speed"?A.speed-=Q:I==="ac"||I==="armor_class"?typeof Q=="string"?A.armor_class=10+(A.ability_modifiers.DEX??0):A.armor_class-=Q:(I==="max_hp"||I==="hp_max")&&(A.hp.max-=Q,A.hp.current=Math.min(A.hp.current,A.hp.max))}static applyEquipmentFeatures(A,B,I,Q){if(B.grantsFeatures)for(const E of B.grantsFeatures)if(typeof E=="string"){const i=KA.getInstance(),e=i.getClassFeatureById(E),a=e?void 0:i.getRacialTraitById(E);if(e||a){const o={featureId:E,source:"equipment",equipmentName:B.name,instanceId:I,sourceType:B.source??"default"};Q.push(o),this.addFeatureToCharacter(A,o)}}else{const i={featureId:E.id,source:"equipment",equipmentName:B.name,instanceId:I,sourceType:B.source??"default"};if(Q.push(i),this.addFeatureToCharacter(A,i),E.effects)for(const e of E.effects)this.applyProperty(A,e,B.name)}}static applyEquipmentSkills(A,B,I,Q){if(B.grantsSkills)for(const E of B.grantsSkills){const i={skillId:E.skillId,level:E.level,source:"equipment",equipmentName:B.name,instanceId:I,sourceType:B.source??"default"};Q.push(i),this.addSkillToCharacter(A,i)}}static addSpellsToCharacter(A,B){A.spells||(A.spells={spell_slots:{},known_spells:[],cantrips:[]});for(const I of B)I.level===0?A.spells.cantrips.includes(I.spellId)||A.spells.cantrips.push(I.spellId):A.spells.known_spells.includes(I.spellId)||A.spells.known_spells.push(I.spellId)}static removeSpellsFromCharacter(A,B){if(A.spells)for(const I of B)if(I.level===0){const Q=A.spells.cantrips.indexOf(I.spellId);Q>-1&&A.spells.cantrips.splice(Q,1)}else{const Q=A.spells.known_spells.indexOf(I.spellId);Q>-1&&A.spells.known_spells.splice(Q,1)}}static addFeatureToCharacter(A,B){A.class_features.includes(B.featureId)||A.class_features.push(B.featureId)}static addSkillToCharacter(A,B){const I=B.skillId.toLowerCase();So(A,I,B.level)}static removeEquipmentFeatures(A,B,I){if(!A.equipment_effects)return;const Q=A.equipment_effects.filter(E=>E.source===B&&E.instanceId===I).flatMap(E=>E.features);for(const E of Q){const i=A.class_features.indexOf(E.featureId);i>-1&&A.class_features.splice(i,1)}}static removeEquipmentSkills(A,B){for(const I of B){const Q=I.skillId.toLowerCase();A.skills[Q]="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,I){if(A.equipment_effects)return A.equipment_effects.find(Q=>Q.source===B&&Q.instanceId===I)}static validateRequirements(A,B,I){const Q=[];for(const E of I)if(E.type==="stat_requirement"){const i=E.target,e=E.value;if(bg(i)){const a=A.ability_scores[i];a<e&&Q.push(`${B.name} requires ${i} ${e}, but character has ${i} ${a}`)}}return Q}static trackStatRequirement(A,B,I){}}class VQ{static ensureInitialized(){co()}static getEquipmentDataStatic(A){return VQ.getEquipmentData(A)}static getEquipmentData(A){return IA.getInstance().get("equipment").find(Q=>Q.name===A)}static getStartingEquipment(A){this.ensureInitialized();const B=LD(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),I=[],Q=[],E=[],i=[...B.weapons,...B.armor,...B.items];for(const a of i){const C=this.getEquipmentData(a);if(C){let o;C.type==="weapon"?o=I:C.type==="armor"?o=Q: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 e=this.getAmmunitionType(A,B.weapons);if(e){const a=this.getAmmunitionQuantity(A),C=E.find(o=>o.name===e);C?C.quantity+=a:E.push({name:e,quantity:a,equipped:!1})}return I.length>0&&(I[0].equipped=!0),Q.length>0&&(Q[0].equipped=!0),{weapons:I,armor:Q,items:E,totalWeight:this.calculateTotalWeight(I,Q,E),equippedWeight:this.calculateEquippedWeight(I,Q,E)}}static addItem(A,B,I=1){this.ensureInitialized();const Q=this.getEquipmentData(B);if(!Q)return A;const E=this.cloneEquipment(A);let i;Q.type==="weapon"?i=E.weapons:Q.type==="armor"?i=E.armor:i=E.items;const e=i.find(a=>a.name===B);return e?I>0&&(e.quantity+=I):i.push({name:B,quantity:Math.max(0,I),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,I=1){if(this.ensureInitialized(),I<=0)return A;const Q=this.cloneEquipment(A);let E;const i=this.getEquipmentData(B);if(!i)return A;i.type==="weapon"?E=Q.weapons:i.type==="armor"?E=Q.armor:E=Q.items;const e=E.findIndex(a=>a.name===B);return e!==-1&&(E[e].quantity>I?E[e].quantity-=I:E.splice(e,1)),Q.totalWeight=this.calculateTotalWeight(Q.weapons,Q.armor,Q.items),Q.equippedWeight=this.calculateEquippedWeight(Q.weapons,Q.armor,Q.items),Q}static equipItem(A,B,I){this.ensureInitialized();const Q=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=Q.weapons:E.type==="armor"?i=Q.armor:i=Q.items;const e=i.find(a=>a.name===B);if(e&&(e.equipped=!0,I)){const a=e.instanceId;PA.equipItem(I,E,a)}return Q.equippedWeight=this.calculateEquippedWeight(Q.weapons,Q.armor,Q.items),Q}static unequipItem(A,B,I){this.ensureInitialized();const Q=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=Q.weapons:E.type==="armor"?i=Q.armor:i=Q.items;const e=i.find(a=>a.name===B);if(e&&(e.equipped=!1,I)){const a=e.instanceId;PA.unequipItem(I,B,a)}return Q.equippedWeight=this.calculateEquippedWeight(Q.weapons,Q.armor,Q.items),Q}static getInventoryList(A){return[...A.weapons,...A.armor,...A.items]}static getEquipmentByType(A,B){return A[B]}static calculateTotalWeight(A,B,I){let Q=0;for(const E of A){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight*E.quantity)}for(const E of B){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight*E.quantity)}for(const E of I){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight*E.quantity)}return Math.round(Q*100)/100}static calculateEquippedWeight(A,B,I){let Q=0;for(const E of A)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight)}for(const E of B)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight)}for(const E of I)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(Q+=i.weight)}return Math.round(Q*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 I=B.some(e=>e==="Longbow"),Q=B.some(e=>e==="Shortbow"),E=B.some(e=>e==="Light Crossbow"),i=B.some(e=>e==="Hand Crossbow");return I||Q?"Arrow":E||i?"Bolt":null}static getAmmunitionQuantity(A){return{Ranger:20,Fighter:20,Rogue:20}[A]||0}static addModification(A,B,I,Q,E){this.ensureInitialized();const i=this.cloneEquipment(A),e=this.getEquipmentData(B);if(!e)return A;let a;e.type==="weapon"?a=i.weapons:e.type==="armor"?a=i.armor:a=i.items;const C=a.find(t=>t.name===B);if(!C)return A;C.modifications||(C.modifications=[]),!Q&&!C.instanceId&&(C.instanceId=`${B}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`);const o=Q||C.instanceId;return C.modifications.push(I),C.equipped&&E&&(PA.unequipItem(E,B,o),this.applyCombinedEffects(E,e,I,o)),i}static removeModification(A,B,I,Q){this.ensureInitialized();const E=this.cloneEquipment(A),i=this.getEquipmentData(B);if(!i)return A;let e;i.type==="weapon"?e=E.weapons:i.type==="armor"?e=E.armor:e=E.items;const a=e.find(s=>s.name===B);if(!a||!a.modifications)return A;const C=a.equipped,o=a.instanceId,t=a.modifications.findIndex(s=>s.id===I);if(t!==-1&&a.modifications.splice(t,1),C&&Q&&(PA.unequipItem(Q,B,o),PA.equipItem(Q,i,o),a.modifications))for(const s of a.modifications)this.applyCombinedEffects(Q,i,s,o);return E}static getActiveEffects(A,B,I){this.ensureInitialized();const Q=this.getEquipmentData(B);if(!Q)return[];let E;Q.type==="weapon"?E=A.weapons:Q.type==="armor"?E=A.armor:E=A.items;const i=E.find(a=>a.name===B&&(!I||a.instanceId===I));if(!i)return[];const e=Q.properties?[...Q.properties]:[];if(i.modifications)for(const a of i.modifications)a.properties&&e.push(...a.properties);return e}static applyCombinedEffects(A,B,I,Q){const E={...B,properties:[...B.properties||[],...I.properties],grantsFeatures:I.addsFeatures,grantsSkills:I.addsSkills,grantsSpells:I.addsSpells};PA.equipItem(A,E,Q)}}class vQ{static applyFeatureEffects(A,B){const I={applied:!1,count:0,errors:[]};if(!B.effects||B.effects.length===0)return I;for(const Q of B.effects)try{this.applySingleEffect(A,Q,B.id),I.applied=!0,I.count++}catch(E){const i=E instanceof Error?E.message:String(E);I.errors.push(`Failed to apply effect from ${B.id}: ${i}`)}return I}static applyMultipleEffects(A,B){const I={applied:!1,count:0,errors:[]};for(const Q of B){const E=this.applyFeatureEffects(A,Q);I.applied=I.applied||E.applied,I.count+=E.count,I.errors.push(...E.errors)}return I}static applySingleEffect(A,B,I){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 I=B.target,Q=B.value;if(bg(I)){mo(A,I,Q);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 I=B.target.toLowerCase(),Q=B.value;So(A,I,Q)}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 I=B.target,Q=B.value;if(I==="speed"){A.speed+=Q;return}if(I.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 qi{static registerExtensions(A){const B=IA.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:I}=A;I.bodyTypes&&I.bodyTypes.length>0&&B.register("appearance.bodyTypes",I.bodyTypes),I.skinTones&&I.skinTones.length>0&&B.register("appearance.skinTones",I.skinTones),I.hairColors&&I.hairColors.length>0&&B.register("appearance.hairColors",I.hairColors),I.hairStyles&&I.hairStyles.length>0&&B.register("appearance.hairStyles",I.hairStyles),I.eyeColors&&I.eyeColors.length>0&&B.register("appearance.eyeColors",I.eyeColors),I.facialFeatures&&I.facialFeatures.length>0&&B.register("appearance.facialFeatures",I.facialFeatures)}}static generate(A,B,I,Q={}){const E=new qB(A),i=Q.level||1,e=Q.gameMode||"standard";Mo();const a=KA.getInstance();Q.extensions&&qi.registerExtensions(Q.extensions);let C;const o=Q.subrace;let t;if(o==="pure")C=void 0,t=Q.forceRace;else if(o!==void 0)if(Q.forceRace)C=o,t=Q.forceRace;else{const aA=a.getRaceForSubrace(o);if(!aA)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=aA,C=o}const s=t||JD.select(E);if(C!==void 0&&o!=="pure"){const aA=a.getAvailableSubraces(s);if(!aA.includes(C))throw new Error(`Invalid subrace "${C}" for race "${s}". Available subraces: ${aA.length>0?aA.join(", "):"none"}`)}else if(C===void 0&&o===void 0){const SA=["pure",...a.getAvailableSubraces(s)],uI=E.randomChoice(SA);C=uI==="pure"?void 0:uI}const n=Q.forceClass||Ji.suggest(B,E),r=Q.forceName||new SD().generateName(A,I,B,n,Q.deterministicName||!0),c=xi.calculateBaseScores(B,E),G=xi.applyRacialBonuses(c,s),D=xi.calculateModifiers(G),h=mC(n);if(!h)throw new Error(`Unknown class: ${n}. Cannot generate character.`);const y=ri(s)?.speed??30,R=h.hit_die+D.CON,Y=10+D.DEX,k=D.DEX,W=SC[i],j=xD.assignSkills(n,E),X={STR:h.saving_throws.includes("STR"),DEX:h.saving_throws.includes("DEX"),CON:h.saving_throws.includes("CON"),INT:h.saving_throws.includes("INT"),WIS:h.saving_throws.includes("WIS"),CHA:h.saving_throws.includes("CHA")},z=qD.generate(A,n,B),QA=a.getClassFeatures(n,i),CA=C?a.getRacialTraitsForSubrace(s,C):a.getBaseRacialTraits(s),dA=VQ.initializeEquipment(n),uA={name:r,race:s,subrace:C,class:n,level:i,ability_scores:G,ability_modifiers:D,proficiency_bonus:W,hp:{current:R,max:R,temp:0},armor_class:Y,initiative:k,speed:y,skills:j,saving_throws:X,racial_traits:[],class_features:[],appearance:z,spells:{spell_slots:{},known_spells:[],cantrips:[]},equipment:dA,xp:{current:0,next_level:HQ[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:e},AA=yo.initializeSpells(n,i,uA),EA=[];for(const aA of QA){const SA=a.validatePrerequisites(aA,uA);SA.valid||console.warn(`Feature "${aA.name}" (${aA.id}) failed prerequisite validation:`,SA.errors),EA.push(aA)}const ZA=[];for(const aA of CA){const SA=a.validatePrerequisites(aA,uA);SA.valid||console.warn(`Trait "${aA.name}" (${aA.id}) failed prerequisite validation:`,SA.errors),ZA.push(aA)}const NA={name:r,race:s,subrace:C,class:n,level:i,ability_scores:G,ability_modifiers:D,proficiency_bonus:W,hp:{current:R,max:R,temp:0},armor_class:Y,initiative:k,speed:y,skills:j,saving_throws:X,racial_traits:ZA.map(aA=>aA.id),class_features:EA.map(aA=>aA.id),appearance:z,spells:AA,equipment:dA,xp:{current:0,next_level:HQ[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:e};if(vQ.applyMultipleEffects(NA,ZA),vQ.applyMultipleEffects(NA,EA),dA){const aA=[...dA.weapons.filter(SA=>SA.equipped),...dA.armor.filter(SA=>SA.equipped),...dA.items.filter(SA=>SA.equipped)];for(const SA of aA){const uI=VQ.getEquipmentDataStatic(SA.name);if(uI){const kG=SA.instanceId;PA.equipItem(NA,uI,kG).applied||(SA.equipped=!1)}}}return yo.filterCharacterSpells(NA)}}function bo(g){return 2595*Math.log10(1+g/700)}function VD(g){return 700*(Math.pow(10,g/2595)-1)}function XQ(g,A){const B=g.sampleRate,I=B/A,Q=g.length,E=Math.ceil(Q/I),i=new Float32Array(Q);for(let a=0;a<g.numberOfChannels;a++){const C=g.getChannelData(a);for(let o=0;o<Q;o++)i[o]+=C[o]/g.numberOfChannels}const e=new Float32Array(E);for(let a=0;a<E;a++){const C=a*I,o=Math.floor(C),t=Math.min(o+1,Q-1),s=C-o;e[a]=i[o]*(1-s)+i[t]*s}return{data:e,originalSampleRate:B,targetSampleRate:A}}function vD(g,A,B,I=0,Q=B/2){const E=A/2+1,i=[],e=bo(I),a=bo(Q),C=[];for(let t=0;t<g+2;t++)C.push(e+t*(a-e)/(g+1));const o=C.map(t=>{const s=VD(t);return Math.floor((A+1)*s/B)});for(let t=0;t<g;t++){const s=new Float32Array(E),n=o[t],r=o[t+1],c=o[t+2];for(let G=n;G<r;G++)r!==n&&(s[G]=(G-n)/(r-n));for(let G=r;G<c;G++)c!==r&&(s[G]=(c-G)/(c-r));i.push(s)}return i}function XD(g,A,B){if(g.length===0)return new Float32Array(0);const I=1/(2*Math.PI*A),Q=1/B,E=I/(I+Q),i=new Float32Array(g.length);i[0]=g[0];for(let e=1;e<g.length;e++)i[e]=E*(i[e-1]+g[e]-g[e-1]);return i}function po(g,A,B){if(g.length===0)return new Float32Array(0);const I=Math.round(A/1e3*B);if(I<=1)return new Float32Array(g);const Q=I/6,E=I,i=new Float32Array(E),e=Math.floor(E/2);let a=0;for(let o=0;o<E;o++){const t=o-e;i[o]=Math.exp(-(t*t)/(2*Q*Q)),a+=i[o]}for(let o=0;o<E;o++)i[o]/=a;const C=new Float32Array(g.length);for(let o=0;o<g.length;o++){let t=0;for(let s=0;s<E;s++){const n=o+s-e,r=n<0?-n:n>=g.length?2*g.length-n-2:n,c=Math.max(0,Math.min(g.length-1,r));t+=g[c]*i[s]}C[o]=t}return C}function KD(g){if(g.length===0)return 0;let A=0;for(let E=0;E<g.length;E++)A+=g[E];const B=A/g.length;let I=0;for(let E=0;E<g.length;E++){const i=g[E]-B;I+=i*i}const Q=I/g.length;return Math.sqrt(Q)}function zD(g){const A=g.length,B=Math.pow(2,Math.ceil(Math.log2(A))),I=new Float32Array(B),Q=new Float32Array(B);for(let a=0;a<A;a++){const C=.5-.5*Math.cos(2*Math.PI*a/(A-1));I[a]=g[a]*C}let E=0;for(let a=0;a<B-1;a++){a<E&&([I[a],I[E]]=[I[E],I[a]],[Q[a],Q[E]]=[Q[E],Q[a]]);let C=B/2;for(;E>=C;)E-=C,C/=2;E+=C}let i=2;for(;i<=B;){const a=-2*Math.PI/i,C=Math.cos(a),o=Math.sin(a);for(let t=0;t<B;t+=i){let s=1,n=0;for(let r=0;r<i/2;r++){const c=t+r,G=t+r+i/2,D=I[G]*s-Q[G]*n,h=I[G]*n+Q[G]*s;I[G]=I[c]-D,Q[G]=Q[c]-h,I[c]+=D,Q[c]+=h;const w=s*C-n*o;n=s*o+n*C,s=w}}i*=2}const e=new Float32Array(B/2+1);for(let a=0;a<e.length;a++){const C=I[a],o=Q[a];e[a]=Math.sqrt(C*C+o*o)}return e}function Yo(g,A,B,I){const Q=[];let E=0;for(;E+A<=g.length;){const i=g.slice(E,E+A),e=zD(i);Q.push(e),E+=B}return{frames:Q,numFrames:Q.length,fftSize:A,hopSize:B,sampleRate:I}}const TD=[{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 OD(g,A){const B=Math.PI*(2*g-1)/(2*A);return 1/(2*Math.sin(B))}function KZ(g,A,B,I){const Q=2*Math.PI*g/A,E=Math.cos(Q),i=Math.sin(Q),e=OD(B,I),a=i/(2*e),C=1+a,o=(1-E)/2/C,t=(1-E)/C,s=(1-E)/2/C,n=-2*E/C,r=(1-a)/C;return{b0:o,b1:t,b2:s,a1:n,a2:r}}function zZ(g,A,B,I){const Q=2*Math.PI*g/A,E=Math.cos(Q),i=Math.sin(Q),e=OD(B,I),a=i/(2*e),C=1+a,o=(1+E)/2/C,t=-(1+E)/C,s=(1+E)/2/C,n=-2*E/C,r=(1-a)/C;return{b0:o,b1:t,b2:s,a1:n,a2:r}}function jD(g,A){const{b0:B,b1:I,b2:Q,a1:E,a2:i}=A,e=new Float32Array(g.length);e[0]=B*g[0],g.length>1&&(e[1]=B*g[1]+I*g[0]-E*e[0]);for(let a=2;a<g.length;a++)e[a]=B*g[a]+I*g[a-1]+Q*g[a-2]-E*e[a-1]-i*e[a-2];return e}function TZ(g,A,B,I,Q){if(g.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>=I/2)throw new Error(`High frequency (${B} Hz) must be less than Nyquist frequency (${I/2} Hz)`);const i=E/2;let e=new Float32Array(g);for(let a=1;a<=i;a++){const C=zZ(A,I,a,E);e=jD(e,C)}for(let a=1;a<=i;a++){const C=KZ(B,I,a,E);e=jD(e,C)}return e}function OZ(g,A,B,I){const Q=TD.find(E=>E.name===A);if(!Q)throw new Error(`Unknown frequency band: ${A}. Valid bands are: low, mid, high`);return TZ(g,Q.lowHz,Q.highHz,B)}const jZ={targetSampleRate:44100,fftWindowSizeMs:23,hopSizeMs:10,smoothWindowMs:10,peakThreshold:.3,bands:TD};class PD{constructor(A={}){if(this.config={...jZ,...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,I=this.config.targetSampleRate,Q=XQ(A,I),E=Math.pow(2,Math.ceil(Math.log2(this.config.fftWindowSizeMs/1e3*I))),i=Math.round(this.config.hopSizeMs/1e3*I),e=this.config.hopSizeMs/1e3,a=1/e,C=new Map,o=[];for(const r of this.config.bands){const c=this.analyzeBand(Q.data,r,I,E,i,e,a);C.set(r.name,c),o.push(c.energyOverTime)}const t=o[0]?.length??0,s=this.combineEnergyProfiles(o,t),n=this.calculateDominantBands(C);return{bands:C,dominantBands:n,energyProfile:s,metadata:{numFrames:t,duration:B,hopSizeSeconds:e,effectiveSampleRate:I,bandsAnalyzed:this.config.bands.map(r=>r.name)}}}analyzeBand(A,B,I,Q,E,i,e){const a=OZ(A,B.name,I),C=Yo(a,Q,E,I),o=C.numFrames,t=new Float32Array(o);for(let y=0;y<o;y++){const R=C.frames[y];let Y=0;for(let k=0;k<R.length;k++)Y+=R[k]*R[k];t[y]=Math.sqrt(Y/R.length)}const s=Math.max(...t);if(s>0)for(let y=0;y<t.length;y++)t[y]/=s;const n=s,r=this.calculateOnsetEnvelope(C.frames),c=po(r,this.config.smoothWindowMs,e),G=Math.max(...c),D=new Float32Array(c.length);if(G>0)for(let y=0;y<c.length;y++)D[y]=c[y]/G;const h=this.findPeaks(D,this.config.peakThreshold),w=h.map(y=>y*i);return{name:B.name,frequencyRange:{lowHz:B.lowHz,highHz:B.highHz},envelope:D,peaks:h,peakTimes:w,energy:n,energyOverTime:t}}calculateOnsetEnvelope(A){const B=A.length,I=new Float32Array(B);I[0]=0;for(let Q=1;Q<B;Q++){const E=A[Q],i=A[Q-1];let e=0;for(let a=0;a<E.length;a++){const C=E[a]-i[a];C>0&&(e+=C)}I[Q]=e}return I}findPeaks(A,B){const I=[];for(let Q=1;Q<A.length-1;Q++)A[Q]>A[Q-1]&&A[Q]>A[Q+1]&&A[Q]>=B&&I.push(Q);return I}combineEnergyProfiles(A,B){const I=new Float32Array(B);for(let Q=0;Q<B;Q++){let E=0;for(const i of A)Q<i.length&&i[Q]>E&&(E=i[Q]);I[Q]=E}return I}calculateDominantBands(A){const B=[];for(const[I,Q]of A)B.push({name:I,energy:Q.energy});return B.sort((I,Q)=>Q.energy-I.energy),B.map(I=>I.name)}}const Uo={low:{threshold:.5,minInterval:.1,adaptiveThresholding:!1},mid:{threshold:.3,minInterval:.08,adaptiveThresholding:!1},high:{threshold:.25,minInterval:.06,adaptiveThresholding:!1}},PZ={baseThreshold:.3,adaptiveThresholding:!1,adaptiveWindowSize:50,minTransientInterval:.02};class _D{constructor(A={}){const{bands:B,bandConfig:I,...Q}=A,E={low:{...Uo.low,...I?.low},mid:{...Uo.mid,...I?.mid},high:{...Uo.high,...I?.high}};if(this.config={...PZ,...Q,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 e=this.config.bandConfig[i];if(e.threshold<0||e.threshold>1)throw new Error(`${i} band threshold must be between 0 and 1, got: ${e.threshold}`);if(e.minInterval<0)throw new Error(`${i} band minInterval must be non-negative, got: ${e.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,I=[],Q=new Set;for(const[e,a]of A.bands){const C=this.detectBandTransients(e,a,A.metadata.hopSizeSeconds);B.set(e,C),I.push(...C),C.forEach(o=>Q.add(o.detectionMethod))}I.sort((e,a)=>e.timestamp-a.timestamp);const E=new Map;for(const[e,a]of B)E.set(e,a.length);const i=I.length>0?I.reduce((e,a)=>e+a.intensity,0)/I.length:0;return{transients:I,bandTransients:B,metadata:{totalTransients:I.length,transientsPerBand:E,duration:A.metadata.duration,averageIntensity:i,detectionMethodsUsed:Array.from(Q)}}}detectBandTransients(A,B,I){const Q=this.config.bandConfig[A],E=this.getDetectionMethod(A),i=E==="energy"?B.energyOverTime:B.envelope;if(!i||i.length===0)return[];const e=Q.adaptiveThresholding?this.calculateAdaptiveThreshold(i,Q.threshold):Q.threshold,C=this.findPeaks(i,e).map(t=>({timestamp:t*I,intensity:i[t],band:A,detectionMethod:E}));return this.applyNonMaximumSuppression(C,Q.minInterval)}applyNonMaximumSuppression(A,B){if(A.length===0)return[];const I=[...A].sort((E,i)=>i.intensity-E.intensity),Q=[];for(const E of I){let i=!1;for(const e of Q)if(Math.abs(E.timestamp-e.timestamp)<B){i=!0;break}i||Q.push(E)}return Q.sort((E,i)=>E.timestamp-i.timestamp),Q}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 I=B??this.config.baseThreshold;if(A.length===0)return I;let Q=0,E=0;for(let s=0;s<A.length;s++)Q+=A[s],A[s]>E&&(E=A[s]);const i=Q/A.length;let e=0;for(let s=0;s<A.length;s++){const n=A[s]-i;e+=n*n}const a=Math.sqrt(e/A.length),o=1+(i>0?a/i:0)*.5,t=I*o;return Math.max(.1,Math.min(.9,t))}findPeaks(A,B){const I=[];for(let Q=1;Q<A.length-1;Q++)A[Q]>A[Q-1]&&A[Q]>A[Q+1]&&A[Q]>=B&&I.push(Q);return I}}const KQ={densityValidation:{maxRetries:0,baseSensitivityReduction:.1,maxCumulativeReduction:.5},minimumTransientIntensity:0,bands:[]};class fo{constructor(A={}){this.config={densityValidation:{maxRetries:A.densityValidation?.maxRetries??KQ.densityValidation.maxRetries,baseSensitivityReduction:A.densityValidation?.baseSensitivityReduction??KQ.densityValidation.baseSensitivityReduction,maxCumulativeReduction:A.densityValidation?.maxCumulativeReduction??KQ.densityValidation.maxCumulativeReduction},minimumTransientIntensity:A.minimumTransientIntensity??KQ.minimumTransientIntensity,bands:A.bands??KQ.bands}}getConfig(){return{...this.config}}quantize(A,B,I){const Q=this.splitTransientsByBand(A.transients),E=B.quarterNoteInterval/6,i=this.processBand(Q.low,"low",E),e=this.processBand(Q.mid,"mid",E),a=this.processBand(Q.high,"high",E),C={low:this.quantizeBand(i.filteredTransients,B,"low",I),mid:this.quantizeBand(e.filteredTransients,B,"mid",I),high:this.quantizeBand(a.filteredTransients,B,"high",I)},o=i.filteredCount+e.filteredCount+a.filteredCount,t=this.aggregateDensityResults([i.densityResult,e.densityResult,a.densityResult],E);return{streams:C,metadata:{densityValidation:t,transientsFilteredByIntensity:o,transientsFilteredByBand:{low:i.filteredCount,mid:e.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,I){const Q=this.config.densityValidation.maxRetries,E=this.config.densityValidation.baseSensitivityReduction,i=this.config.densityValidation.maxCumulativeReduction;let e=0,a=A;if(this.config.minimumTransientIntensity>0){const n=a.length;a=a.filter(r=>r.intensity>=this.config.minimumTransientIntensity),e=n-a.length}let C=this.config.minimumTransientIntensity,o=0,t=0;for(;t<=Q;){const n=this.validateBandDensity(a,B,I,t,o);if(n.isValid)return{filteredTransients:a,filteredCount:e,densityResult:n};if(t>=Q)return console.warn(`[${B}] Density validation: Max retries (${Q}) reached. Proceeding with ${a.length} transients. Min interval: ${(n.minIntervalDetected*1e3).toFixed(1)}ms (required: ${(I*1e3).toFixed(1)}ms)`),{filteredTransients:a,filteredCount:e,densityResult:n};t++;const r=Math.min(E,i-o);o+=r,C=Math.min(this.config.minimumTransientIntensity+o,1);const c=a.length;a=a.filter(D=>D.intensity>=C);const G=c-a.length;e+=G,console.warn(`[${B}] Density validation retry ${t}: Threshold increased to ${(C*100).toFixed(1)}%, Filtered ${G} transients, ${a.length} remaining`)}const s=this.validateBandDensity(a,B,I,t,o);return{filteredTransients:a,filteredCount:e,densityResult:s}}validateBandDensity(A,B,I,Q,E,i=this.config.minimumTransientIntensity){const e=A.length,a=Math.min(this.config.minimumTransientIntensity+E,1);if(A.length===0)return{band:B,isValid:!0,minIntervalDetected:1/0,requiredMinInterval:I,retryCount:Q,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:e};const C=[...A].sort((s,n)=>s.timestamp-n.timestamp);let o=1/0;for(let s=1;s<C.length;s++){const n=C[s].timestamp-C[s-1].timestamp;n<o&&(o=n)}const t=o>=I;return{band:B,isValid:t,minIntervalDetected:o,requiredMinInterval:I,retryCount:Q,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:e}}aggregateDensityResults(A,B){let I=0,Q=0,E=1/0,i=!0;for(const e of A)e.retryCount>I&&(I=e.retryCount),e.sensitivityReduction>Q&&(Q=e.sensitivityReduction),e.minIntervalDetected<E&&(E=e.minIntervalDetected),e.isValid||(i=!1);return{isValid:i,bands:{low:A.find(e=>e.band==="low"),mid:A.find(e=>e.band==="mid"),high:A.find(e=>e.band==="high")},maxRetryCount:I,maxSensitivityReduction:Q}}decideGrids(A,B,I){const Q=[],E=B.quarterNoteInterval,i=this.getBandGridType(I),e=[...A].sort((a,C)=>a.timestamp-C.timestamp);for(let a=0;a<B.beats.length;a++){const C=B.beats[a],o=C.timestamp,t=a<B.beats.length-1?B.beats[a+1].timestamp:C.timestamp+E,s=e.filter(n=>n.timestamp>=o&&n.timestamp<t);s.length!==0&&(i?Q.push({beatIndex:a,selectedGrid:i,transientCount:s.length,confidence:1}):Q.push(this.detectGrid(s,C,a,E)))}return Q}quantizeToGrids(A,B,I,Q){const E=[],i=B.quarterNoteInterval,e=[...A].sort((C,o)=>C.timestamp-o.timestamp),a=new Map;for(const C of Q)a.set(C.beatIndex,C);for(let C=0;C<B.beats.length;C++){const o=B.beats[C],t=a.get(C);if(!t)continue;const s=o.timestamp,n=C<B.beats.length-1?B.beats[C+1].timestamp:o.timestamp+i,r=e.filter(c=>c.timestamp>=s&&c.timestamp<n);for(const c of r){const G=this.quantizeTransient(c,o,C,t.selectedGrid,i);G&&E.push(G)}}return E}quantizeBand(A,B,I,Q){const E=Q?Q(A,B,I):this.decideGrids(A,B,I),i=this.quantizeToGrids(A,B,I,E),e=this.deduplicateBeats(i);return{audioId:B.audioId,duration:B.duration,beats:e,gridDecisions:E,quarterNoteInterval:B.quarterNoteInterval}}deduplicateBeats(A){const B=new Map;for(const I of A){const Q=`${I.beatIndex}:${I.gridPosition}:${I.gridType}`,E=B.get(Q);(!E||I.intensity>E.intensity)&&B.set(Q,I)}return Array.from(B.values()).sort((I,Q)=>I.timestamp-Q.timestamp)}getBandGridType(A){switch(A){case"low":return"straight_8th";case"mid":case"high":return null}}detectGrid(A,B,I,Q){const E=this.calculateStraightGrid(B.timestamp,Q),i=this.calculateTripletGrid(B.timestamp,Q);let e=0,a=0,C=0;for(const r of A){const c=this.calculateOffsetFromGrid(r,E),G=this.calculateOffsetFromGrid(r,i);e+=c,a+=G,C++}const o=C>0?e/C:0,t=C>0?a/C:0,s=o<=t?"straight_16th":"triplet_8th",n=Math.abs(o-t);return{beatIndex:I,selectedGrid:s,straightAvgOffset:o,tripletAvgOffset:t,transientCount:C,confidence:n}}calculateStraightGrid(A,B){const I=[],Q=B/4;for(let E=0;E<4;E++)I.push(A+E*Q);return I}calculateTripletGrid(A,B){const I=[],Q=B/3;for(let E=0;E<3;E++)I.push(A+E*Q);return I}calculate8thGrid(A,B){const I=[],Q=B/2;for(let E=0;E<2;E++)I.push(A+E*Q);return I}calculateOffsetFromGrid(A,B){let I=1/0;for(const Q of B){const E=Math.abs(A.timestamp-Q);E<I&&(I=E)}return I*1e3}quantizeTransient(A,B,I,Q,E){let i,e;switch(Q){case"straight_8th":i=1,e=E/2;break;case"straight_16th":i=3,e=E/4;break;case"triplet_8th":i=2,e=E/3;break}const a=Math.round((A.timestamp-B.timestamp)/e);if(a<0||a>i)return null;const C=B.timestamp+a*e,o=Math.abs(A.timestamp-C)*1e3;return{timestamp:C,detectedTimestamp:A.timestamp,beatIndex:I,gridPosition:a,gridType:Q,intensity:A.intensity,band:A.band,quantizationError:o}}}class $D{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:I}=B,Q=I>=this.restrictTripletBpm;return A.map(E=>{const{selectedGrid:i}=E;return i==="straight_8th"?E:i==="straight_16th"&&I>=this.restrict16thBpm?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:i==="triplet_8th"&&Q?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:E})}}const ko={rules:[new $D],enabled:!0};class Ad{constructor(A=ko,B){this.config=A,this.rhythmQuantizer=B??new fo}getConfig(){return{...this.config}}decideGrids(A,B,I){const Q=this.rhythmQuantizer.decideGrids(A,B,I),E={bpm:B.quarterNoteBpm,quarterNoteInterval:B.quarterNoteInterval,band:I,transients:A};return this.applyRules(Q,E)}applyRules(A,B){if(this.config.enabled===!1)return A;let I=A;for(const Q of this.config.rules)Q.applies(B.bpm,B)&&(I=Q.apply(I,B));return I}}const _Z={phraseSizes:[1,2,4,8],minOccurrences:3,topSignificantCount:10,includePhrasesWithoutVariation:!1,minNotesPerPhrase:g=>1+g};class Bd{constructor(A={}){this.config={..._Z,...A}}analyze(A){const B={low:this.analyzeBand(A.low,"low"),mid:this.analyzeBand(A.mid,"mid"),high:this.analyzeBand(A.high,"high")},I=[...B.low.phrases,...B.mid.phrases,...B.high.phrases],Q=new Map;Q.set("low",B.low.phrases),Q.set("mid",B.mid.phrases),Q.set("high",B.high.phrases);const E=new Map;for(const C of this.config.phraseSizes){const o=I.filter(t=>t.sizeInBeats===C);o.length>0&&E.set(C,o)}const e=[...I].sort((C,o)=>o.significance-C.significance).slice(0,this.config.topSignificantCount),a=I.filter(C=>C.hasVariation&&C.availableForReuse);return{phrases:I,phrasesByBand:Q,mostSignificantPhrases:e,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 I=Math.max(...A.beats.map(a=>a.beatIndex),0),Q=new Map;for(const a of this.config.phraseSizes)for(let C=0;C<=I-a+1;C++){const o=this.extractPhraseCandidate(A,C,a,B);if(o){const t=Q.get(o.hash);t?t.push(o):Q.set(o.hash,[o])}}const E=[];for(const[a,C]of Q){if(C.length<this.config.minOccurrences)continue;const o=C[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=C.map(c=>({beatIndex:c.startBeatIndex,startTimestamp:c.startTimestamp,endTimestamp:c.endTimestamp})),n=this.calculateSignificance(o.sizeInBeats,C.length),r=t&&C.length>=this.config.minOccurrences;E.push({id:a,pattern:o.pattern,sizeInBeats:o.sizeInBeats,sourceBand:B,occurrences:s,significance:n,hasVariation:t,availableForReuse:r})}E.sort((a,C)=>C.significance-a.significance);const i=new Map;for(const a of this.config.phraseSizes){const C=E.filter(o=>o.sizeInBeats===a);C.length>0&&i.set(a,C)}const e=E.filter(a=>a.hasVariation);return{band:B,phrases:E,phrasesBySize:i,phrasesWithVariation:e}}extractPhraseCandidate(A,B,I,Q){const E=B+I-1,i=A.beats.filter(t=>t.beatIndex>=B&&t.beatIndex<=E);if(i.length===0)return null;const e=i.map(t=>({...t,beatIndex:t.beatIndex-B})),a=this.hashPattern(e,I),C=Math.min(...i.map(t=>t.timestamp)),o=Math.max(...i.map(t=>t.timestamp));return{hash:a,pattern:e,sizeInBeats:I,startBeatIndex:B,startTimestamp:C,endTimestamp:o}}hashPattern(A,B){const Q=[...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}_${Q.join("|")}`}hasPatternVariation(A,B){if(A.length===0)return!1;if(A.some(e=>e.gridType==="triplet_8th")||A.some(e=>e.gridPosition===1||e.gridPosition===3))return!0;const I=A.map(e=>e.intensity),Q=Math.max(...I),E=Math.min(...I);if(Q-E>.1)return!0;if(A.length===B&&A.every(a=>a.gridPosition===0))return!1;const i=new Set(A.map(e=>e.gridPosition));return!(i.size===2&&i.has(0)&&i.has(2)&&this.countBeatsWithNoteCount(A,2)===B)}countBeatsWithNoteCount(A,B){const I=new Map;for(const E of A){const i=I.get(E.beatIndex)??0;I.set(E.beatIndex,i+1)}let Q=0;for(const E of I.values())E===B&&Q++;return Q}calculateSignificance(A,B){const I=A,Q=Math.log2(B+1);return I*Q}}const $Z={beatsPerSection:8,sparseThreshold:1,denseThreshold:1.5};class gd{constructor(A={}){this.config={...$Z,...A}}analyze(A,B,I){const Q=B/60,E={low:this.analyzeBand(A.streams.low,"low",Q,I),mid:this.analyzeBand(A.streams.mid,"mid",Q,I),high:this.analyzeBand(A.streams.high,"high",Q,I)};[...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),e=this.calculateCombinedMetrics(i,Q,I),a=this.calculateSectionMetrics(i,Q,I);return{bandMetrics:E,combinedMetrics:e,sections:a,perBeatDensity:i}}analyzeBand(A,B,I,Q){const E=A.beats,e=(E.length>0?Math.max(...E.map(h=>h.beatIndex)):0)+1,a=new Map;for(const h of E){const w=a.get(h.beatIndex);w?(w.count++,w.intensities.push(h.intensity)):a.set(h.beatIndex,{count:1,intensities:[h.intensity]})}const C=[];let o=0;for(let h=0;h<e;h++){const w=a.get(h),y=w?.count??0,R=w?w.intensities.reduce((Y,k)=>Y+k,0)/w.intensities.length:0;C.push({beatIndex:h,transientCount:y,bands:y>0?[B]:[],averageIntensity:R}),o+=y}const t=C.map(h=>h.transientCount);let s;Q&&Q>0?s=o/Q:s=e>0?o/e*I:0;const n=t.length>0?Math.min(...t)*I:0,r=t.length>0?Math.max(...t)*I:0,c=this.calculateVariance(t,s/I)*I*I,G=this.categorizeDensity(s),D=this.determineNaturalDifficulty(G);return{band:B,totalBeats:e,totalTransients:o,notesPerSecond:s,minNotesPerSecond:n,maxNotesPerSecond:r,variance:c,densityCategory:G,naturalDifficulty:D,perBeatDensity:C}}calculateCombinedPerBeatDensity(A,B,I){const Q=[...A.beats,...B.beats,...I.beats],i=(Q.length>0?Math.max(...Q.map(C=>C.beatIndex)):0)+1,e=new Map;for(const C of A.beats)this.addToBeatData(e,C,"low");for(const C of B.beats)this.addToBeatData(e,C,"mid");for(const C of I.beats)this.addToBeatData(e,C,"high");const a=[];for(let C=0;C<i;C++){const o=e.get(C);if(o){const t=o.intensities.length>0?o.intensities.reduce((s,n)=>s+n,0)/o.intensities.length:0;a.push({beatIndex:C,transientCount:o.count,bands:Array.from(o.bands),averageIntensity:t})}else a.push({beatIndex:C,transientCount:0,bands:[],averageIntensity:0})}return a}addToBeatData(A,B,I){const Q=A.get(B.beatIndex);if(Q)Q.count++,Q.bands.add(I),Q.intensities.push(B.intensity);else{const E=new Set;E.add(I),A.set(B.beatIndex,{count:1,bands:E,intensities:[B.intensity]})}}calculateCombinedMetrics(A,B,I){const Q=A.reduce((a,C)=>a+C.transientCount,0);let E;if(I&&I>0)E=Q/I;else{const a=A.length;E=a>0?Q/a*B:0}const i=this.categorizeDensity(E),e=this.determineNaturalDifficulty(i);return{totalTransients:Q,notesPerSecond:E,densityCategory:i,naturalDifficulty:e}}calculateSectionMetrics(A,B,I){const Q=[],E=this.config.beatsPerSection,i=A.length;for(let e=0;e<i;e+=E){const a=Math.min(e+E-1,i-1),C=A.slice(e,a+1),o=C.reduce((h,w)=>h+w.transientCount,0),t=C.length,s=t>0?o/t*B:0,n=C.map(h=>h.transientCount),r=n.length>0?Math.min(...n)*B:0,c=n.length>0?Math.max(...n)*B:0,G=this.categorizeDensity(s),D=this.determineNaturalDifficulty(G);Q.push({startBeat:e,endBeat:a,beatCount:t,totalTransients:o,notesPerSecond:s,minNotesPerSecond:r,maxNotesPerSecond:c,densityCategory:G,naturalDifficulty:D})}return Q}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(Q=>Math.pow(Q-B,2)).reduce((Q,E)=>Q+E,0)/A.length}getConfig(){return{...this.config}}}const Id={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}},AN={low:.8,mid:.95,high:1},BN={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 gN(g){const A=BN[g];return{...Id,...A,bandBiasWeights:{...AN}}}class Qd{constructor(A={}){this.config={...Id,...A}}score(A,B,I){const Q=[],E={low:[],mid:[],high:[]},i=[...A.streams.low.beats,...A.streams.mid.beats,...A.streams.high.beats],e=i.length>0?Math.max(...i.map(n=>n.beatIndex)):0,a=e+1,C=["low","mid","high"];for(let n=0;n<a;n+=this.config.beatsPerSection){const r=Math.min(n+this.config.beatsPerSection-1,e),c={start:n,end:r};for(const G of C){const D=this.scoreSection(A.streams[G],G,c,B,I);Q.push(D),E[G].push(D.score)}}const o={low:E.low.reduce((n,r)=>n+r,0),mid:E.mid.reduce((n,r)=>n+r,0),high:E.high.reduce((n,r)=>n+r,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(Q);return{sectionScores:Q,bandTotals:o,bandAverages:t,sectionWinners:s,config:{...this.config}}}scoreSection(A,B,I,Q,E){const i=A.beats.filter(s=>s.beatIndex>=I.start&&s.beatIndex<=I.end),e=this.calculateIOIVariance(i),a=this.calculateSyncopationLevel(i),C=this.calculatePhraseSignificance(Q,B,I),o=this.calculateDensityFactor(E,B,I);let t=e*this.config.ioiVarianceWeight+a*this.config.syncopationWeight+C*this.config.phraseSignificanceWeight+o*this.config.densityWeight;if(this.config.bandBiasWeights){const s=this.config.bandBiasWeights[B]??1;t*=s}return{beatRange:I,band:B,score:t,factors:{ioiVariance:e,syncopationLevel:a,phraseSignificance:C,densityFactor:o}}}calculateIOIVariance(A){if(A.length<2)return 0;const B=[...A].sort((a,C)=>a.timestamp-C.timestamp),I=[];for(let a=1;a<B.length;a++)I.push(B[a].timestamp-B[a-1].timestamp);if(I.length===0)return 0;const Q=I.reduce((a,C)=>a+C,0)/I.length,E=I.reduce((a,C)=>a+Math.pow(C-Q,2),0)/I.length,i=Math.sqrt(E),e=Q>0?i/Q:0;return Math.min(e,1)}calculateSyncopationLevel(A){if(A.length===0)return 0;let B=0,I=0;for(const Q of A){const i=this.config.offbeatGridPositions[Q.gridType].includes(Q.gridPosition),e=Q.intensity;i&&(B+=e),I+=e}return I===0?0:B/I}calculatePhraseSignificance(A,B,I){const Q=A.phrasesByBand.get(B)??[];if(Q.length===0)return 0;let E=0,i=0;for(const a of Q){i=Math.max(i,a.significance);for(const C of a.occurrences){const o=C.beatIndex+a.sizeInBeats-1;if(C.beatIndex<=I.end&&o>=I.start){const t=Math.max(C.beatIndex,I.start),r=(Math.min(o,I.end)-t+1)/a.sizeInBeats;E+=a.significance*r;break}}}if(i===0)return 0;const e=E/i;return Math.min(e,1)}calculateDensityFactor(A,B,I){const i=A.bandMetrics[B].perBeatDensity.filter(n=>n.beatIndex>=I.start&&n.beatIndex<=I.end);if(i.length===0)return 0;const e=i.reduce((n,r)=>n+r.transientCount,0)/i.length,a=this.config.bpm!=null?this.config.bpm/60:1,C=e*a;return Math.exp(-Math.pow(C-1,2)/(2*Math.pow(.75,2)))}determineSectionWinners(A){const B=new Map;for(const Q of A){const E=`${Q.beatRange.start}-${Q.beatRange.end}`,i=B.get(E);i?i.push(Q):B.set(E,[Q])}const I=[];for(const[,Q]of B){if(Q.length===0)continue;const E=[...Q].sort((C,o)=>o.score-C.score),i=E[0],e=E[1],a=e?i.score-e.score:i.score;I.push({beatRange:i.beatRange,winner:i.band,score:i.score,margin:a})}return I.sort((Q,E)=>Q.beatRange.start-E.beatRange.start),I}getConfig(){return{...this.config}}updateConfig(A){this.config={...this.config,...A}}}const IN={transitionOverlapBeats:0,preserveGridDecisions:!0},QN=1,EN=1.5;class Ed{constructor(A={}){this.config={...IN,...A}}generate(A,B,I,Q){const E=B.sectionWinners,i={low:0,mid:0,high:0},e={low:0,mid:0,high:0},C=E.filter(D=>{const h=["low","mid","high"];let w=!1;for(const y of h)if(A.streams[y].beats.filter(k=>k.beatIndex>=D.beatRange.start&&k.beatIndex<=D.beatRange.end).length>0){w=!0;break}return w}).map(D=>({beatRange:D.beatRange,sourceBand:D.winner,score:D.score,margin:D.margin}));for(const D of C)e[D.sourceBand]++;const o=[];for(const D of C){const h=A.streams[D.sourceBand],w=this.extractSectionBeats(h,D.beatRange,D.sourceBand);o.push(...w),i[D.sourceBand]+=w.length}o.sort((D,h)=>D.timestamp-h.timestamp);const t=this.deduplicateBeats(o),s=A.streams.low.quarterNoteInterval,n=60/s,r=this.determineNaturalDifficulty(t,I,n,Q),c=C.length,G={totalBeats:t.length,sectionCount:c,beatsPerBand:i,sectionsPerBand:{low:c>0?e.low/c:0,mid:c>0?e.mid/c:0,high:c>0?e.high/c:0}};return{beats:t,sections:C,naturalDifficulty:r,quarterNoteInterval:s,metadata:G}}extractSectionBeats(A,B,I){return A.beats.filter(Q=>Q.beatIndex>=B.start&&Q.beatIndex<=B.end).map(Q=>({...Q,sourceBand:I}))}deduplicateBeats(A){const B=new Map;for(const I of A){const Q=Math.round(I.timestamp*1e3),E=B.get(Q);(!E||I.intensity>E.intensity)&&B.set(Q,I)}return Array.from(B.values()).sort((I,Q)=>I.timestamp-Q.timestamp)}determineNaturalDifficulty(A,B,I,Q){if(A.length===0)return"easy";let E;if(Q&&Q>0)E=A.length/Q;else{const e=Math.max(...A.map(a=>a.beatIndex))+1;E=A.length/e*(I/60)}return E<QN?"easy":E>EN?"hard":"medium"}getConfig(){return{...this.config}}}const Li={strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},iN={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 eN(g){return{...iN[g]}}function id(g){return g%3===0?3:2}function ed(g,A){return g%A===0}function ad(g,A){return g%A!==0}function Cd(g,A){let B=g[0];for(const I of g)if(I.startBeat<=A)B=I;else break;return B}function od(g,A,B){if(B==="neutral")return!1;const I=id(A);return B==="natural"?ed(g,I):ad(g,I)}class td{constructor(A={}){this.config={...Li,...A}}getConfig(){return{...this.config}}balance(A,B){const I={shiftedToDownbeat:0,emptyMeasuresFilled:0,proximityShifts:0,beatsAdded:0,beatsShifted:0,marginRemovals:0};let Q=[...A.beats];return Q=this.shiftLoneSubdivisionNotes(Q,B,I),Q=this.fillEmptyMeasures(Q,B,I),Q=this.enforceDownbeatProximity(Q,B,I),Q=this.removeMarginNotes(Q,B.duration,I),Q.sort((E,i)=>E.timestamp-i.timestamp),{composite:{...A,beats:Q,metadata:{...A.metadata,totalBeats:Q.length}},stats:I}}shiftLoneSubdivisionNotes(A,B,I){if(!B.downbeatConfig?.segments)return A;const Q=new Map;for(const i of A){const e=B.beats[i.beatIndex];if(e){const a=e.measureNumber;Q.has(a)||Q.set(a,[]),Q.get(a).push(i)}}const E=[];for(const i of A){const e=B.beats[i.beatIndex];if(!e){E.push(i);continue}const a=e.measureNumber;if((Q.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),I.shiftedToDownbeat++,I.beatsShifted++}else E.push(i)}return E}fillEmptyMeasures(A,B,I){if(!this.config.fillEmptyMeasures||!B.downbeatConfig?.segments)return A;let Q=1/0,E=-1/0;for(const C of B.beats)Q=Math.min(Q,C.measureNumber),E=Math.max(E,C.measureNumber);if(Q===1/0)return A;const i=new Map;for(const C of A){const o=B.beats[C.beatIndex];if(o){const t=o.measureNumber;i.has(t)||i.set(t,[]),i.get(t).push(C)}}const e=new Map;for(const C of A)e.set(C.beatIndex,C.gridType);const a=[];for(let C=Q;C<=E;C++)if((i.get(C)||[]).length===0){const t=B.beats.findIndex(s=>s.measureNumber===C&&s.isDownbeat);if(t>=0){let s="straight_8th";for(let c=1;c<=8;c++){const G=t-c,D=t+c;if(e.has(G)){s=e.get(G);break}if(e.has(D)){s=e.get(D);break}}const r={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(r),I.emptyMeasuresFilled++,I.beatsAdded++}}return[...A,...a]}enforceDownbeatProximity(A,B,I){const Q=this.config.downbeatProximityRange;if(Q<0)return A;const E=new Set;for(const e of A)e.gridPosition===0&&E.add(e.beatIndex);const i=[];for(const e of A){if(e.gridPosition===0){i.push(e);continue}let a=!1;const C=Math.ceil(Q);for(let o=0;o<=C&&!(o>Q);o++)if(o===0){if(E.has(e.beatIndex)){a=!0;break}}else if(E.has(e.beatIndex-o)||E.has(e.beatIndex+o)){a=!0;break}if(a)i.push(e);else{const o={...e,gridPosition:0,timestamp:B.beats[e.beatIndex]?.timestamp??e.timestamp,balancerAction:"proximity_shift"};i.push(o),E.add(e.beatIndex),I.proximityShifts++,I.beatsShifted++}}return i}removeMarginNotes(A,B,I){const Q=this.config.marginSeconds;if(Q<=0||B<=0)return A;const E=B-Q;return A.filter(i=>i.timestamp<Q||i.timestamp>E?(I.marginRemovals++,!1):!0)}}const aN=["straight_16th","triplet_8th","straight_8th","quarter_triplet","straight_4th"],Zo={straight_16th:4,straight_8th:2,triplet_8th:3,straight_4th:1,quarter_triplet:1},vB={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}}},sd=70,nd=70,rd=120;function ng(g,A){if(g==="natural")return[...vB.natural.allowedGridTypes];if(g==="easy")return["straight_4th","quarter_triplet"];if(g==="medium")return["straight_8th","quarter_triplet"];if(g==="hard")return A>=nd?["straight_8th","quarter_triplet"]:[...vB.hard.allowedGridTypes];if(g==="custom")return[...vB.custom.allowedGridTypes];const B=g;throw new Error(`Unhandled difficulty: ${B}`)}const CN={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 cd(g,A){const B=CN[g.maxGridType]??[g.maxGridType];if(!g.bpmBasedQuantization)return[...B];const I=g.restrictBpm??sd,Q=g.quarterNoteBpm??rd;let E=[...B];return A>=I&&(E=E.filter(i=>i!=="straight_16th"&&i!=="triplet_8th")),A>Q&&(E=E.filter(i=>i!=="straight_8th")),E}function Gd(g,A){if(g.length===0||A<=0)return 0;const B=60/A;return Math.max(...g.map(Q=>Zo[Q]))/B}const oN={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 tN(g,A,B){return B!==void 0?ng(A,B).includes(g):vB[A].allowedGridTypes.includes(g)}function sN(g,A){return A!==void 0?ng(g,A):[...vB[g].allowedGridTypes]}function Vi(g,A,B,I){const Q=I??(B!==void 0?ng(A,B):vB[A].allowedGridTypes);if(Q.includes(g))return g;switch(g){case"straight_16th":return Q.includes("straight_4th")&&!Q.includes("straight_8th")?"straight_4th":"straight_8th";case"triplet_8th":return"quarter_triplet";case"straight_8th":return"straight_4th";default:return g}}function nN(g){return g}function hd(g,A,B){const I=[],Q=B!==void 0?ng(A,B):vB[A].allowedGridTypes;for(const E of g)Q.includes(E.gridType)||I.push({beat:E,gridType:E.gridType,suggestedConversion:Vi(E.gridType,A,B)});return{isValid:I.length===0,violations:I,totalBeats:g.length,violationCount:I.length}}class vi{constructor(A={}){this.currentUnifiedBeatMap=null,this.config={...oN,...A}}lockGridPerBeatIndex(A,B,I,Q,E){const i=this.enforceSingleGridPerBeat(A),e=new Map;if(i.length===0)return{beats:[],gridLock:e};const a=Math.max(...i.map(t=>t.beatIndex)),C=new Map;for(const t of i){const s=C.get(t.beatIndex)??[];s.push(t),C.set(t.beatIndex,s)}for(const[t,s]of C)e.set(t,s[0].gridType);const o=E??ng(B,I);for(let t=0;t<=a;t++){if(e.has(t))continue;if(Q?.has(t)){const r=Q.get(t);e.set(t,r.selectedGrid);continue}let s=!1;for(const r of[1,-1,2,-2,3,-3]){const c=t+r;if(e.has(c)){e.set(t,e.get(c)),s=!0;break}}if(s)continue;const n=o[0]??"straight_8th";e.set(t,n)}return{beats:i,gridLock:e}}generate(A,B,I,Q){this.currentUnifiedBeatMap=B;const E=A.naturalDifficulty,i=this.generateVariant(A,"easy",E,B,I,Q),e=this.generateVariant(A,"medium",E,B,I,Q),a=this.generateVariant(A,"hard",E,B,I,Q);this.validateGridLockResult(i.beats,"easy"),this.validateGridLockResult(e.beats,"medium"),this.validateGridLockResult(a.beats,"hard");const C={difficulty:"natural",beats:this.enforceSingleGridPerBeat([...A.beats]),isUnedited:!0,editType:"none",editAmount:0};this.validateVariant(i,"easy"),this.validateVariant(e,"medium"),this.validateVariant(a,"hard");const o=B?.duration??120;if(i.densityValidation=this.validateDensityInRange(i,o),e.densityValidation=this.validateDensityInRange(e,o),a.densityValidation=this.validateDensityInRange(a,o),this.config.logConversions){const t=s=>{const n=s.densityValidation,r=n.targetRange.max===1/0?"∞":n.targetRange.max.toFixed(1),c=n.inRange?"✓":"✗";return`${s.difficulty}: ${n.density.toFixed(2)} nps (target [${n.targetRange.min}, ${r}]) ${c}`};console.log(`[DifficultyVariantGenerator] Density validation summary:
|
|
50
50
|
${t(i)}
|
|
51
51
|
${t(e)}
|
|
52
52
|
${t(a)}`)}return{easy:i,medium:e,hard:a,natural:C}}generateAtDensity(A,B,I,Q,E){this.currentUnifiedBeatMap=I;const i=I?.quarterNoteBpm??120,e=I?.duration??120;this.calculateDensity(A.beats,e);const a=cd(B,i),C=Gd(a,i);let o=B.targetDensity,t=!1;B.targetDensity>C&&(o=C,t=!0,console.warn(`[DifficultyVariantGenerator] Target density ${B.targetDensity.toFixed(2)} nps exceeds max achievable ${C.toFixed(2)} nps for grid types [${a.join(", ")}] at ${i} BPM. Clamping to ${o.toFixed(2)} nps.`));const{beats:s,gridLock:n}=this.lockGridPerBeatIndex(A.beats,"custom",i,E,a),r=this.calculateDensity(s,e),c=1e-10,G=Math.max(o,1e-10),D=s.some(h=>!a.includes(h.gridType));if(this.config.logConversions&&console.log(`[DifficultyVariantGenerator] generateAtDensity: current=${r.toFixed(2)} nps, target=${G.toFixed(2)} nps, maxGridType=${B.maxGridType}, allowedTypes=[${a.join(", ")}], clamped=${t}`),r>G*(1+c)){const h=this.simplifyBeats(s,"custom",A.quarterNoteInterval,!1,Q,i,n,e,a,o);return{difficulty:"custom",beats:this.enforceSingleGridPerBeat(h.beats),isUnedited:!1,editType:"simplified",editAmount:h.metadata.totalBeatsBefore>0?(h.metadata.totalBeatsBefore-h.metadata.totalBeatsAfter)/h.metadata.totalBeatsBefore:0,conversionMetadata:h.metadata,densityClamped:t}}else if(r<o*(1-c)){const h=this.enhanceBeats(s,"custom",i,I,Q,E,A.quarterNoteInterval,n,a,o),w=this.enforceSingleGridPerBeat(h.beats),y=h.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:"custom",beats:w,isUnedited:!1,editType:y,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}}else{if(D){this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Density approximately equal (${r.toFixed(2)} ≈ ${o.toFixed(2)}), but grid restrictions needed`);const w=this.simplifyBeats(s,"custom",A.quarterNoteInterval,!1,Q,i,n,e,a,o);return{difficulty:"custom",beats:this.enforceSingleGridPerBeat(w.beats),isUnedited:w.metadata.beatsRemoved===0&&!t,editType:w.metadata.beatsRemoved>0?"simplified":"none",editAmount:w.metadata.totalBeatsBefore>0?(w.metadata.totalBeatsBefore-w.metadata.totalBeatsAfter)/w.metadata.totalBeatsBefore:0,conversionMetadata:w.metadata,densityClamped:t}}return{difficulty:"custom",beats:this.enforceSingleGridPerBeat(s),isUnedited:!t,editType:"none",editAmount:0}}}generateAtDensities(A,B,I,Q,E){const i=new Map;for(const{label:e,config:a}of B){const C={...A,beats:A.beats.map(t=>({...t}))},o=this.generateAtDensity(C,a,I,Q,E);i.set(e,o)}return i}validateVariant(A,B){const I=hd(A.beats,B);if(I.isValid)this.config.logConversions&&console.log(`[DifficultyVariantGenerator] ${B} variant validated: ${I.totalBeats} beats, no subdivision violations`);else if(console.warn(`[DifficultyVariantGenerator] ${B} variant has ${I.violationCount} subdivision violations out of ${I.totalBeats} beats. This indicates a bug in the variant generation logic.`),this.config.logConversions){for(const Q of I.violations.slice(0,5))console.warn(` - Beat at index ${Q.beat.beatIndex}, position ${Q.beat.gridPosition}, grid: ${Q.gridType} (suggested: ${Q.suggestedConversion})`);I.violations.length>5&&console.warn(` ... and ${I.violations.length-5} more violations`)}}validateGridLockResult(A,B){const I=this.validateSingleGridPerBeat(A);if(!I.isValid&&(console.warn(`[DifficultyVariantGenerator] ${B} variant has ${I.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 Q of I.violations.slice(0,5))console.warn(` - Beat index ${Q.beatIndex} has mixed grids: ${Q.gridTypes.join(", ")}`);I.violations.length>5&&console.warn(` ... and ${I.violations.length-5} more violations`)}}validateDensityInRange(A,B){const I=this.calculateDensity(A.beats,B),Q=vB[A.difficulty].targetDensityRange,E=I>=Q.min&&(Q.max===1/0||I<=Q.max);if(E){if(this.config.logConversions){const i=Q.max===1/0?"∞":Q.max.toFixed(2);console.log(`[DifficultyVariantGenerator] ${A.difficulty} variant density ${I.toFixed(2)} nps is within target range [${Q.min.toFixed(2)}, ${i}] ✓`)}}else{const i=Q.max===1/0?"∞":Q.max.toFixed(2);console.warn(`[DifficultyVariantGenerator] ${A.difficulty} variant density ${I.toFixed(2)} nps is OUTSIDE target range [${Q.min.toFixed(2)}, ${i}]. This may occur for edge cases (short songs, extreme tempos).`)}return{inRange:E,density:I,targetRange:Q,difficulty:A.difficulty}}generateVariant(A,B,I,Q,E,i){const e=B===I,a=Q?.quarterNoteBpm??120,C=Q?.duration??120,o=ng(B,a),{beats:t,gridLock:s}=this.lockGridPerBeatIndex(A.beats,B,a,i);if(e){if(t.every(D=>o.includes(D.gridType))){const{targetCount:D}=this.calculateBeatCountTarget(t.length,C,B);if(t.length<D){const h=this.enhanceBeats(t,B,a,Q,E,i,A.quarterNoteInterval,s),w=h.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:B,beats:h.beats,isUnedited:!1,editType:w,editAmount:h.metadata.totalBeatsBefore>0?(h.metadata.totalBeatsAfter-h.metadata.totalBeatsBefore)/h.metadata.totalBeatsBefore:0,enhancementMetadata:h.metadata}}return{difficulty:B,beats:[...t],isUnedited:!0,editType:"none",editAmount:0}}const G=this.simplifyBeats(t,B,A.quarterNoteInterval,!1,E,a,s,C);return{difficulty:B,beats:G.beats,isUnedited:!1,editType:"simplified",editAmount:G.metadata.totalBeatsBefore>0?(G.metadata.totalBeatsBefore-G.metadata.totalBeatsAfter)/G.metadata.totalBeatsBefore:0,conversionMetadata:G.metadata}}const n=this.needsSimplification(B,I),r=this.needsEnhancement(B,I);if(n){const c=this.isHeavySimplification(B,I),G=this.simplifyBeats(t,B,A.quarterNoteInterval,c,E,a,s,C),{targetCount:D}=this.calculateBeatCountTarget(G.beats.length,C,B);if(G.beats.length<D-1){const h=this.enhanceBeats(G.beats,B,a,Q,E,i,A.quarterNoteInterval,s),w=h.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:B,beats:h.beats,isUnedited:!1,editType:w,editAmount:1,conversionMetadata:G.metadata,enhancementMetadata:h.metadata}}return{difficulty:B,beats:G.beats,isUnedited:!1,editType:"simplified",editAmount:G.metadata.totalBeatsBefore>0?(G.metadata.totalBeatsBefore-G.metadata.totalBeatsAfter)/G.metadata.totalBeatsBefore:0,conversionMetadata:G.metadata}}if(r){const c=this.enhanceBeats(t,B,a,Q,E,i,A.quarterNoteInterval,s);let G=c.beats;if(G.some(w=>!o.includes(w.gridType))){const w=[];for(const y of G)if(o.includes(y.gridType))w.push(y);else{const R=this.convertBeatGridType(y,B,A.quarterNoteInterval,a);R&&w.push(R)}G=this.deduplicateConvertedBeats(w)}const h=c.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:B,beats:G,isUnedited:!1,editType:h,editAmount:c.metadata.totalBeatsBefore>0?(c.metadata.totalBeatsAfter-c.metadata.totalBeatsBefore)/c.metadata.totalBeatsBefore:0,patternsInserted:c.metadata.insertedPatternIds.length>0?c.metadata.insertedPatternIds:void 0,enhancementMetadata:c.metadata}}return{difficulty:B,beats:[...t],isUnedited:!0,editType:"none",editAmount:0}}simplifyBeats(A,B,I,Q=!1,E,i=120,e,a=120,C,o){const t={sixteenthToEighth:0,tripletToQuarterTriplet:0,eighthToQuarter:0,beatsRemoved:0,totalBeatsBefore:A.length,totalBeatsAfter:0},s=this.buildPhraseMembershipMap(E),n=e?A:this.enforceSingleGridPerBeat(A);t.totalBeatsBefore=n.length;const r=C??ng(B,i);if(n.every(W=>r.includes(W.gridType))&&!Q){const W=o!==void 0?Math.round(o*a):this.calculateBeatCountTarget(n.length,a,B).targetCount,j=this.reduceDensityToTarget(n,B,t,s,i,W,a);return t.totalBeatsAfter=j.length,{beats:j,metadata:t}}let G=n;Q&&(G=this.filterBeatsForHeavySimplification(n,t,s));const D=[];for(const W of G){if(r.includes(W.gridType)){D.push(W);continue}const j=e?.get(W.beatIndex),X=this.convertBeatGridType(W,B,I,i,j,r);if(X)if(D.push(X),W.gridType==="straight_16th"){if(t.sixteenthToEighth++,this.config.logConversions){const z=X.gridType==="straight_4th"?"quarter":"8th";console.log(`[DifficultyVariantGenerator] Converted 16th note at beat ${W.beatIndex} position ${W.gridPosition} to ${z} note`)}}else W.gridType==="triplet_8th"?(t.tripletToQuarterTriplet++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Converted 8th triplet at beat ${W.beatIndex} position ${W.gridPosition} to quarter triplet`)):W.gridType==="straight_8th"&&(t.eighthToQuarter++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Converted 8th note at beat ${W.beatIndex} position ${W.gridPosition} to quarter note`));else t.beatsRemoved++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Removed beat at beat ${W.beatIndex} position ${W.gridPosition} (grid: ${W.gridType})`)}const h=this.deduplicateConvertedBeats(D);t.beatsRemoved+=D.length-h.length;const w=D.length-h.length,y=this.calculateDensity(h,a),R=o!==void 0?Math.round(o*a):this.calculateBeatCountTarget(h.length,a,B).targetCount,Y=o??this.calculateBeatCountTarget(h.length,a,B).targetDensity;if(h.length<=R)return this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Grid conversion achieved target density: ${y.toFixed(2)} notes/sec (target midpoint ${Y.toFixed(2)} nps, ${R} beats) for ${B}`+(w>0?` (${w} beats collapsed)`:"")),t.totalBeatsAfter=h.length,{beats:h,metadata:t};const k=this.reduceDensityToTarget(h,B,t,s,i,R,a);return t.totalBeatsAfter=k.length,{beats:k,metadata:t}}filterBeatsForHeavySimplification(A,B,I=new Map){const Q=this.config.heavySimplificationIntensityThreshold,E=[];for(const i of A){const e=this.isStrongBeat(i.beatIndex),a=i.gridPosition===0,C=i.gridPosition===1||i.gridPosition===3,o=this.shouldPreserveForPhrase(i,I,Q);e||o||a&&i.intensity>=Q*.7||C&&i.intensity>=Q||i.gridPosition===2&&i.intensity>=Q*.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: ${e})`))}return E}isStrongBeat(A){const B=this.config.rhythmicBalanceConfig?.strongBeatEmphasis??"natural";if(B==="neutral")return!1;const I=this.currentUnifiedBeatMap;if(!I){const a=A%4;return a===0||a===2}const Q=I.beats[A];if(!Q){const a=A%4;return a===0||a===2}const E=I.downbeatConfig?.segments;if(!E||E.length===0){const a=A%4;return a===0||a===2}const e=Cd(E,A).timeSignature.beatsPerMeasure;return od(Q.beatInMeasure,e,B)}calculateDensity(A,B){return A.length===0||B<=0?0:A.length/B}calculateBeatCountTarget(A,B,I){const Q=vB[I].targetDensityRange;if(I==="natural"||I==="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}[I];let e;switch(this.config.densityTargetStrategy){case"lower":e=i*.75+Q.min*.25;break;case"upper":{const s=Q.max===1/0?i*1.5:Q.max;e=i*.75+s*.25;break}default:e=i;break}const a=Q.max===1/0?e:Q.max;e=Math.max(Q.min,Math.min(a,e));const C=Math.round(Q.min*B),o=Q.max===1/0?1/0:Math.round(Q.max*B);return{targetCount:Math.round(e*B),maxCount:o,minCount:C,targetDensity:e}}calculateBeatsToAdd(A,B,I,Q){const E=this.calculateBeatCountTarget(A,B,Q),i=Math.max(0,E.targetCount-A),e=ng(Q,I),a=this.getMaxBeatsPerIndexFromGridTypes(e);return{beatsToAdd:i,targetCount:E.targetCount,maxBeatsPerIndex:a}}getMaxBeatsPerIndexFromGridTypes(A){let B=1;for(const I of A){const Q=Zo[I];Q>B&&(B=Q)}return B}getMaxBeatsForGridType(A){return Zo[A]??1}distributeBeatsAcrossIndices(A,B,I,Q,E,i){const e=new Map;let a=A;for(let n=0;n<=Q;n++){const r=B.get(n)??[];e.set(n,r.length)}if(a<=0)return e;const C=n=>{const r=I.get(n);return r?i&&!i.includes(r)?this.getMaxBeatsPerIndexFromGridTypes(i):this.getMaxBeatsForGridType(r):i?this.getMaxBeatsPerIndexFromGridTypes(i):4},o=[],t=[];for(let n=0;n<=Q;n++){const r=e.get(n)??0,c=C(n);r===0?o.push(n):r<c&&t.push(n)}const s=this.groupConsecutiveEmptyIndices(o);s.sort((n,r)=>{const c=n.length-r.length;if(c!==0)return c;const G=mg(Pg(E,`gap:${n[0]}`)),D=mg(Pg(E,`gap:${r[0]}`));return G-D});for(const n of s){if(a<=0)break;const r=n.length<=2;for(const c of n){if(a<=0)break;const G=C(c);let D;r?D=Math.min(G,a,2):D=Math.min(G,a,1),D>0&&(e.set(c,D),a-=D)}}t.sort((n,r)=>{const c=e.get(n)??0,G=e.get(r)??0,D=C(n),h=C(r),w=D-c,R=h-G-w;if(R!==0)return R;const Y=mg(Pg(E,`partial:${n}`)),k=mg(Pg(E,`partial:${r}`));return Y-k});for(const n of t){if(a<=0)break;const r=e.get(n)??0,G=C(n)-r;if(G>0){const D=Math.min(G,a);e.set(n,r+D),a-=D}}if(a>0)for(const n of o){if(a<=0)break;const r=e.get(n)??0,G=C(n)-r;if(G>0){const D=Math.min(G,a);e.set(n,r+D),a-=D}}return e}groupConsecutiveEmptyIndices(A){if(A.length===0)return[];const B=[];let I=[A[0]];for(let Q=1;Q<A.length;Q++){const E=A[Q-1],i=A[Q];i===E+1?I.push(i):(B.push(I),I=[i])}return B.push(I),B}reduceDensityToTarget(A,B,I,Q=new Map,E=120,i,e=120){const a=vB[B].targetDensityRange,C=this.calculateDensity(A,e);if(i!==void 0&&A.length<=i)return this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Density ${C.toFixed(2)} notes/sec already at or below target midpoint (${i} beats) for ${B}`),A;if(C<=a.max&&i===void 0)return this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Density ${C.toFixed(2)} notes/sec already within target range [${a.min}, ${a.max}] for ${B}`),A;this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Reducing density from ${C.toFixed(2)} notes/sec to target max ${a.max} notes/sec for ${B}`);const o=this.buildDownbeatCountMap(A),t=A.map(y=>({beat:y,priority:this.calculateRemovalPriority(y,Q,o)}));t.sort((y,R)=>y.priority-R.priority);const s=new Set;let n=A.length;const r=this.config.maxReductionPasses;let c=0;for(let y=1;y<=r;y++){c=y;let R=0;const Y=y===r;let k,W,j=!1;y===1?(k=1-this.config.densityReductionMinIntensity,W=this.config.moderateSimplificationIntensityThreshold):y===2?(k=1-this.config.densityReductionMinIntensity-.15,W=this.config.moderateSimplificationIntensityThreshold-.1):(j=!0,k=0,W=0);for(const{beat:X,priority:z}of t)if(!s.has(X)){if(i!==void 0){if(n-1<=i)break}else if((n-1)/e<=a.max)break;if(j){if(this.isStrongBeat(X.beatIndex))continue}else if(z>=k||X.intensity>=W)continue;s.add(X),n--,R++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Pass ${y}: Removed beat at index ${X.beatIndex} position ${X.gridPosition} (priority: ${z.toFixed(2)}, intensity: ${X.intensity.toFixed(2)})`)}if(this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Pass ${y}${Y?" (final)":""}: Removed ${R} beats, density now: ${(n/e).toFixed(2)} notes/sec`),i!==void 0){if(n<=i)break}else if(n/e<=a.max)break}const G=n/e;if((i!==void 0?n>i:G>a.max)&&this.config.logConversions){const y=i!==void 0?`${i} beats (midpoint ${(i/e).toFixed(2)} nps)`:`${a.max} notes/sec`;console.warn(`[DifficultyVariantGenerator] Could not reach target density ${y} for ${B} after ${r} passes. Final density: ${G.toFixed(2)} notes/sec (${n} beats remaining)`)}const h=A.filter(y=>!s.has(y));I.reductionPasses=c,I.beatsRemoved+=s.size;const w=Math.ceil(a.min*e);if(h.length<w&&A.length>0){const y=t.filter(({beat:R})=>s.has(R)).sort((R,Y)=>Y.priority-R.priority);for(const{beat:R}of y){if(h.length>=w)break;h.push(R),I.beatsRemoved--}}return h}buildDownbeatCountMap(A){const B=new Map,I=this.currentUnifiedBeatMap;for(const Q of A){if(Q.gridPosition!==0)continue;let E;I?.beats[Q.beatIndex]?E=I.beats[Q.beatIndex].measureNumber:E=Math.floor(Q.beatIndex/4),B.set(E,(B.get(E)??0)+1)}return B}calculateRemovalPriority(A,B,I=new Map){const Q=this.config.rhythmicBalanceConfig?.strongBeatEmphasis??"natural";let E=.5;if(Q!=="neutral"&&this.isStrongBeat(A.beatIndex)&&(E+=.3),A.gridPosition===0){E+=.2;const e=this.currentUnifiedBeatMap;let a;e?.beats[A.beatIndex]?a=e.beats[A.beatIndex].measureNumber:a=Math.floor(A.beatIndex/4),(I.get(a)??0)===1&&(E+=.2)}E+=A.intensity*.3;const i=B.get(A.beatIndex);if(i&&i.length>0){const e=Math.max(...i.map(a=>a.significance));E+=Math.min(.15,e*.05)}return(A.gridPosition===1||A.gridPosition===3)&&(E-=.1),Math.max(0,Math.min(1,E))}convertBeatGridType(A,B,I,Q=120,E,i){const e=E??A.gridType,a=Vi(e,B,Q,i);if(a===e)return{...A,gridType:a};let C,o,t;switch(e){case"straight_16th":{const s=I/4;if(t=A.timestamp-A.gridPosition*s,a==="straight_4th")C=0,o=t;else{A.gridPosition===1||A.gridPosition===3?C=A.gridPosition===1?0:2:C=A.gridPosition;const n=I/2;o=t+(C===0?0:n)}break}case"triplet_8th":{const s=I/3;t=A.timestamp-A.gridPosition*s,C=0,o=t;break}case"straight_8th":{const s=I/2;t=A.timestamp-A.gridPosition*s,C=0,o=t;break}default:return{...A,gridType:A.gridType}}return{...A,gridType:a,gridPosition:C,timestamp:o}}deduplicateConvertedBeats(A){const B=new Map;for(const I of A){const Q=`${I.beatIndex}:${I.gridPosition}:${I.gridType}`,E=B.get(Q);(!E||I.intensity>E.intensity)&&B.set(Q,I)}return Array.from(B.values()).sort((I,Q)=>I.timestamp-Q.timestamp)}needsSimplification(A,B){const I=["easy","medium","hard"],Q=I.indexOf(A),E=I.indexOf(B);return Q<E}needsEnhancement(A,B){const I=["easy","medium","hard"],Q=I.indexOf(A),E=I.indexOf(B);return Q>E}isHeavySimplification(A,B){return B==="hard"&&A==="easy"}enhanceBeats(A,B,I,Q,E,i,e=.5,a,C,o){const t=Q?.duration??120,s={totalBeatsBefore:A.length,totalBeatsAfter:0,patternsInserted:0,interpolatedBeats:0,insertedPatternIds:[]},n=X=>{if(C){if(C.includes(X))return X;const z=["straight_16th","triplet_8th","straight_8th","quarter_triplet","straight_4th"],QA=z.indexOf(X);for(let CA=QA+1;CA<z.length;CA++)if(C.includes(z[CA]))return z[CA];return C[C.length-1]??X}return Vi(X,B,I)};if(A.length===0)return s.totalBeatsAfter=0,{beats:[],metadata:s};let r=a?A:this.enforceSingleGridPerBeat(A);if(C&&r.some(z=>!C.includes(z.gridType))){const z=[];for(const CA of r)if(C.includes(CA.gridType))z.push(CA);else{const dA=this.convertBeatGridType(CA,B,e,I,void 0,C);dA&&z.push(dA)}r=this.deduplicateConvertedBeats(z)}s.totalBeatsBefore=r.length;const c=this.groupBeatsByIndex(r),G=Math.max(...Array.from(c.keys()));let D;if(o!==void 0){const X=Math.round(o*t);D=Math.max(0,X-r.length);const z=Math.max(0,3*r.length);D=Math.min(D,z)}else D=this.calculateBeatsToAdd(r.length,t,I,B).beatsToAdd;const h=this.config.seed??`enhance:${G}:${r.length}`,w=this.distributeBeatsAcrossIndices(D,c,a??new Map,G,h,C),y=[],R=new Map,Y=(X,z)=>`${X}:${z}`;for(const X of r){const z=Y(X.beatIndex,X.gridPosition);R.has(z)||R.set(z,X.gridType)}for(let X=0;X<=G;X++){const z=c.get(X)??[],QA=w.get(X)??0;if(z.length>=QA){y.push(...z);continue}const CA=QA-z.length;if(z.length===0){const EA=a?.get(X),ZA=EA?n(EA):void 0,NA=this.createBeatsForEmptyIndex(X,CA,Q,i,e,c,R,ZA),Pa=ZA??this.getGridForBeatIndex(X,NA,i);for(const aA of NA){const SA=Y(aA.beatIndex,aA.gridPosition);!R.has(SA)&&aA.gridType===Pa&&(R.set(SA,aA.gridType),y.push(aA),s.interpolatedBeats++)}continue}const dA=a?.get(X)??z[0].gridType,uA=n(dA);let AA=0;if(this.config.preferPatternInsertion&&E){const EA=this.tryInsertPattern(z,X,CA,E,R,uA);AA=EA.beatsAdded,EA.patternId&&(s.patternsInserted++,s.insertedPatternIds.push(EA.patternId))}if(AA<CA){const EA=this.interpolateBeats(z,X,CA-AA,e,R,uA,Q);for(const ZA of EA){const NA=Y(ZA.beatIndex,ZA.gridPosition);R.has(NA)||(R.set(NA,ZA.gridType),y.push(ZA),s.interpolatedBeats++)}}y.push(...z)}const k=y.sort((X,z)=>X.beatIndex!==z.beatIndex?X.beatIndex-z.beatIndex:X.gridPosition-z.gridPosition);let W;a?(this.validateSingleGridPerBeat(k).isValid,W=k):W=this.enforceSingleGridPerBeat(k);const j=this.deduplicateEnhancedBeats(W);return s.totalBeatsAfter=j.length,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Enhanced beats for ${B}: ${s.totalBeatsBefore} → ${s.totalBeatsAfter} beats (patterns: ${s.patternsInserted}, interpolated: ${s.interpolatedBeats})`),{beats:j,metadata:s}}groupBeatsByIndex(A){const B=new Map;for(const I of A){const Q=B.get(I.beatIndex);Q?Q.push(I):B.set(I.beatIndex,[I])}return B}calculateTargetBeatsPerBeat(A,B,I){const Q=new Map;for(let E=0;E<=I;E++){const i=A.get(E);if(i){const e=Math.min(Math.ceil(i.length*B),4);Q.set(E,e)}else{const e=Math.min(Math.ceil(B*.7),4);e>=2&&Q.set(E,e)}}return Q}tryInsertPattern(A,B,I,Q,E,i){const a=Q.patternLibrary.filter(h=>h.sizeInBeats<=this.config.maxPatternInsertionSize&&h.availableForReuse);if(a.length===0)return{beatsAdded:0};const C=a.filter(h=>h.pattern.some(w=>w.gridType===i));if(C.length===0)return{beatsAdded:0};C.sort((h,w)=>w.significance-h.significance);const o=C[0],t=o.pattern.filter(h=>h.beatIndex===0),s=new Set(A.map(h=>h.gridPosition)),n=(h,w)=>`${h}:${w}`,r=t.filter(h=>!(h.gridType!==i||s.has(h.gridPosition)||E.has(n(B,h.gridPosition))));if(r.length===0)return{beatsAdded:0};const c=r.slice(0,I),G=o.sourceBand,D=c.map(h=>({...h,beatIndex:B,band:G,sourceBand:G,intensity:h.intensity*.8}));for(const h of D)E.set(n(h.beatIndex,h.gridPosition),h.gridType);return{beatsAdded:D.length,patternId:o.id}}createBeatsForEmptyIndex(A,B,I,Q,E=.5,i,e,a){let C=a??"straight_16th",o="mid",t="mid";if(!a&&Q){const y=Q.get(A);y&&(C=y.selectedGrid)}if(!a&&!Q?.has(A)&&i)for(const y of[1,-1,2,-2,3,-3]){const R=i.get(A+y);if(R&&R.length>0){C=R[0].gridType,o=R[0].band,t=R[0].sourceBand;break}}const s=new Set;if(e){const y=(R,Y)=>`${R}:${Y}`;for(let R=0;R<4;R++)e.has(y(A,R))&&s.add(R)}const r={straight_16th:4,straight_8th:2,triplet_8th:3,straight_4th:1,quarter_triplet:1}[C],c=[];for(let y=0;y<r;y++)s.has(y)||c.push(y);c.sort((y,R)=>{const Y=k=>k===0?0:k===r-1?2:1;return Y(y)-Y(R)});const G=c.slice(0,B),D=I?.beats[A]?.timestamp??A*E,w={straight_16th:E/4,straight_8th:E/2,triplet_8th:E/3,straight_4th:E,quarter_triplet:E}[C];return G.map(y=>({timestamp:D+y*w,beatIndex:A,gridPosition:y,gridType:C,intensity:this.config.interpolatedBeatIntensity*.8,band:o,sourceBand:t,quantizationError:0}))}interpolateBeats(A,B,I,Q=.5,E,i,e){if(I<=0||A.length===0)return[];const a=i??A[0].gridType,o=(y=>y==="straight_16th"?4:y==="straight_8th"?2:y==="straight_4th"||y==="quarter_triplet"?1:3)(a),t=(y,R)=>`${y}:${R}`,s=new Set(A.map(y=>y.gridPosition));if(E)for(let y=0;y<o;y++)E.has(t(B,y))&&s.add(y);const n=[];for(let y=0;y<o;y++)s.has(y)||n.push(y);n.sort((y,R)=>(y===0||y===3?2:1)-(R===0||R===3?2:1));const r=n.slice(0,I),c=A[0],G=e?.beats[B]?.timestamp??B*Q,h={straight_16th:Q/4,straight_8th:Q/2,triplet_8th:Q/3,straight_4th:Q,quarter_triplet:Q}[a];return r.map(y=>({timestamp:G+y*h,beatIndex:B,gridPosition:y,gridType:a,intensity:this.config.interpolatedBeatIntensity,band:c.band,sourceBand:c.sourceBand,quantizationError:0}))}getGridForBeatIndex(A,B,I,Q){if(B.length>0)return B[0].gridType;if(I?.has(A))return I.get(A).selectedGrid;if(Q)for(const E of[1,-1,2,-2,3,-3]){const i=Q.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 I=new Map;for(const[E,i]of B){let e="straight_16th",a=0;for(const[C,o]of i)o>a&&(a=o,e=C);I.set(E,e)}const Q=new Map;for(const E of A){const i=`${E.beatIndex}:${E.gridPosition}`,e=Q.get(i),a=I.get(E.beatIndex);e?E.gridType===a&&e.gridType!==a&&Q.set(i,E):Q.set(i,E)}return Array.from(Q.values())}enforceSingleGridPerBeat(A){const B=new Map;for(const Q of A){const E=B.get(Q.beatIndex)??[];E.push(Q),B.set(Q.beatIndex,E)}const I=[];for(const[,Q]of B){if(Q.length<=1){I.push(...Q);continue}const E=new Set(Q.map(C=>C.gridType));if(E.size<=1){I.push(...Q);continue}let i="straight_16th",e=0;for(const C of E){const o=Q.filter(t=>t.gridType===C).reduce((t,s)=>t+s.intensity,0);o>e&&(e=o,i=C)}const a=Q.filter(C=>C.gridType===i);if(this.config.logConversions&&a.length<Q.length){const C=Q.filter(o=>o.gridType!==i);console.log(`[DifficultyVariantGenerator] Enforced single grid at beat ${Q[0].beatIndex}: kept ${i} (${a.length} beats), removed ${C.map(o=>o.gridType).join(", ")} (${C.length} beats)`)}I.push(...a)}return I.sort((Q,E)=>Q.timestamp-E.timestamp)}validateSingleGridPerBeat(A){const B=new Map;for(const Q of A){const E=B.get(Q.beatIndex)??[];E.push(Q),B.set(Q.beatIndex,E)}const I=[];for(const[Q,E]of B){if(E.length<=1)continue;const i=new Set(E.map(e=>e.gridType));i.size>1&&I.push({beatIndex:Q,gridTypes:Array.from(i)})}if(I.length>0&&this.config.logConversions){console.warn(`[DifficultyVariantGenerator] Grid validation found ${I.length} violations. This indicates a bug in grid lock implementation.`);for(const Q of I.slice(0,5))console.warn(` - Beat index ${Q.beatIndex} has mixed grids: ${Q.gridTypes.join(", ")}`)}return{isValid:I.length===0,violations:I}}getConfig(){return{...this.config}}buildPhraseMembershipMap(A){const B=new Map;if(!A||!this.config.preservePhraseBoundaries)return B;const I=A.phrases.filter(Q=>Q.hasVariation);for(const Q of I)for(const E of Q.occurrences)for(let i=0;i<Q.sizeInBeats;i++){const e=E.beatIndex+i,a=B.get(e)??[];a.push(Q),B.set(e,a)}return B}shouldPreserveForPhrase(A,B,I){if(!this.config.preservePhraseBoundaries)return!1;const Q=B.get(A.beatIndex);if(!Q||Q.length===0)return!1;const E=Q.reduce((o,t)=>t.significance>o.significance?t:o),e=A.intensity-I>=-.15,C=E.significance>=1.5;return e&&C?(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 No={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 rN(g){return No[g]}function cN(){return Object.keys(No)}const GN={difficulty:"medium",outputMode:"composite",measureStartOffset:0,minimumTransientIntensity:0,transientConfig:void 0,scoringConfig:void 0,phraseAnalyzerConfig:void 0,rhythmicBalanceConfig:Li,seed:void 0,verbose:!1,enableCache:!0,cacheMaxAge:1800*1e3,skipDifficultyVariants:!1};class kg{constructor(A={}){this.cache=new Map,this.cacheHits=0,this.cacheMisses=0;const B={...Li,...A.rhythmicBalanceConfig};this.options={...GN,...A,rhythmicBalanceConfig:B},this.multiBandAnalyzer=new PD,this.transientDetector=new _D({bandConfig:this.options.transientConfig}),this.rhythmQuantizer=new fo({minimumTransientIntensity:this.options.minimumTransientIntensity,densityValidation:this.options.densityValidation}),this.phraseAnalyzer=new Bd(this.options.phraseAnalyzerConfig),this.densityAnalyzer=new gd,this.streamScorer=new Qd(this.options.scoringConfig),this.compositeGenerator=new Ed,this.variantGenerator=new vi({seed:this.options.seed,rhythmicBalanceConfig:B}),this.rhythmicBalancer=new td(this.options.rhythmicBalanceConfig),this.tempoAwareQuantizer=new Ad(this.options.tempoQuantizationConfig??ko,this.rhythmQuantizer)}generateCacheKey(A,B,I){return`${A}:${B}:${I}`}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,I]of this.cache.entries())A-I.timestamp>this.options.cacheMaxAge&&this.cache.delete(B)}getCacheStats(){let A=0;const B=[];let I=null;for(const[Q,E]of this.cache.entries()){const i=Q.split(":")[1];B.includes(i)||B.push(i);try{A+=JSON.stringify(E.result).length*2}catch{A+=1e3}(I===null||E.timestamp<I)&&(I=E.timestamp)}return{entryCount:this.cache.size,estimatedSize:A,cachedPhases:B,oldestEntry:I,hits:this.cacheHits,misses:this.cacheMisses}}isCached(A,B){const I=this.createConfigFingerprint(),Q=this.generateCacheKey(A,B,I);return this.cache.has(Q)}getOptions(){return{...this.options}}async generate(A,B,I,Q){const E=(R,Y,k)=>{this.options.verbose&&console.log(`[RhythmGenerator] [${R}] ${Math.round(Y*100)}%: ${k}`),Q?.(R,Y,k)};I?.throwIfAborted();const i=this.generateCacheKey(B.audioId,"variants",this.createConfigFingerprint()),e=this.getFromCache(i);if(e)return E("Cache",1,"Retrieved complete result from cache"),e;E("Phase 1",0,"Starting multi-band analysis"),I?.throwIfAborted();const a=this.analyzeMultiBand(A);E("Phase 1",.2,`Analyzed ${a.bands.size} frequency bands`),I?.throwIfAborted();const C=this.detectTransients(a);E("Phase 1",.4,`Detected ${C.transients.length} transients`),I?.throwIfAborted();const o=this.quantizeTransients(C,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"),I?.throwIfAborted(),E("Phase 2",0,"Starting phrase and density analysis"),I?.throwIfAborted();const t=this.analyzePhrases(o.streams);E("Phase 2",.3,`Detected ${t.phrases.length} rhythmic phrases`),I?.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"),I?.throwIfAborted(),E("Phase 3",0,"Starting scoring and composite generation"),I?.throwIfAborted();const n=this.scoreStreams(o,t,s,B.quarterNoteBpm);E("Phase 3",.2,`Scored ${n.sectionWinners.length} sections`),I?.throwIfAborted();const r=this.generateComposite(o,n,s,B.duration);E("Phase 3",.4,`Generated composite with ${r.beats.length} beats, natural difficulty: ${r.naturalDifficulty}`),I?.throwIfAborted();const c=this.rhythmicBalancer.balance(r,B),G=c.composite,D=c.stats;E("Phase 3",.6,`Balanced composite: ${G.beats.length} beats (${D.beatsAdded} added, ${D.beatsShifted} shifted for rhythmic structure)`);const h=this.options.skipDifficultyVariants?null:this.generateDifficultyVariants(G,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"),I?.throwIfAborted();const w={difficulty:this.options.difficulty,bandsAnalyzed:["low","mid","high"],transientsDetected:C.metadata.totalTransients,transientsFilteredByIntensity:o.metadata.transientsFilteredByIntensity,densityValidationRetries:o.metadata.densityValidation.maxRetryCount,phrasesDetected:t.phrases.length,averageDensity:s.combinedMetrics.notesPerSecond,naturalDifficulty:G.naturalDifficulty,generationConfig:this.options,duration:A.duration,totalBeats:B.beats.length,balanceStats:D},y={difficultyVariants:h,bandStreams:o.streams,composite:G,analysis:{transientAnalysis:C,quantizationResult:o,phraseAnalysis:t,densityAnalysis:s,scoringResult:n},metadata:w};return this.setCache(i,y),y}analyzeMultiBand(A){return this.multiBandAnalyzer.analyze(A)}detectTransients(A){return this.transientDetector.detect(A)}quantizeTransients(A,B){return this.rhythmQuantizer.quantize(A,B,(I,Q,E)=>this.tempoAwareQuantizer.decideGrids(I,Q,E))}analyzePhrases(A){return this.phraseAnalyzer.analyze(A)}analyzeDensity(A,B,I){return this.densityAnalyzer.analyze(A,B,I)}scoreStreams(A,B,I,Q){return this.streamScorer.updateConfig({bpm:Q}),this.streamScorer.score(A,B,I)}generateComposite(A,B,I,Q){return this.compositeGenerator.generate(A,B,I,Q)}generateDifficultyVariants(A,B,I,Q){const E=this.collectGridDecisions(I);return this.variantGenerator.generate(A,Q,B,E)}collectGridDecisions(A){const B=new Map,I=[...A.streams.low.gridDecisions,...A.streams.mid.gridDecisions,...A.streams.high.gridDecisions];for(const Q of I){const E=B.get(Q.beatIndex);(!E||Q.confidence>E.confidence)&&B.set(Q.beatIndex,Q)}return B}static async quickGenerate(A,B){return new kg().generate(A,B)}static async generateForDifficulty(A,B,I){return(await new kg().generate(A,B)).difficultyVariants[I]}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:I}=await Promise.resolve().then(()=>Eg),Q=kg.toJSON(A);await I(B,Q,"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(()=>Eg),I=await B(A,"utf-8");return kg.fromJSON(I)}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,I])=>({band:B,transients:I.map(Q=>this.serializeTransientResult(Q))})),metadata:{totalTransients:A.metadata.totalTransients,transientsPerBand:Array.from(A.metadata.transientsPerBand.entries()).map(([B,I])=>({band:B,count:I})),duration:A.metadata.duration,averageIntensity:A.metadata.averageIntensity,detectionMethodsUsed:A.metadata.detectionMethodsUsed}}}static deserializeTransientAnalysis(A){const B=new Map;for(const Q of A.bandTransients)B.set(Q.band,Q.transients.map(E=>this.deserializeTransientResult(E)));const I=new Map;for(const Q of A.metadata.transientsPerBand)I.set(Q.band,Q.count);return{transients:A.transients.map(Q=>this.deserializeTransientResult(Q)),bandTransients:B,metadata:{totalTransients:A.metadata.totalTransients,transientsPerBand:I,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,I])=>({band:B,phrases:I.map(Q=>this.serializeRhythmicPhrase(Q))})),mostSignificantPhrases:A.mostSignificantPhrases.map(B=>this.serializeRhythmicPhrase(B)),phrasesBySize:Array.from(A.phrasesBySize.entries()).map(([B,I])=>({size:B,phrases:I.map(Q=>this.serializeRhythmicPhrase(Q))})),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 Q of A.phrasesByBand)B.set(Q.band,Q.phrases.map(E=>this.deserializeRhythmicPhrase(E)));const I=new Map;for(const Q of A.phrasesBySize)I.set(Q.size,Q.phrases.map(E=>this.deserializeRhythmicPhrase(E)));return{phrases:A.phrases.map(Q=>this.deserializeRhythmicPhrase(Q)),phrasesByBand:B,mostSignificantPhrases:A.mostSignificantPhrases.map(Q=>this.deserializeRhythmicPhrase(Q)),phrasesBySize:I,patternLibrary:A.patternLibrary.map(Q=>this.deserializeRhythmicPhrase(Q)),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,I])=>({size:B,phrases:I.map(Q=>this.serializeRhythmicPhrase(Q))})),phrasesWithVariation:A.phrasesWithVariation.map(B=>this.serializeRhythmicPhrase(B))}}static deserializeBandPhraseAnalysis(A){const B=new Map;for(const I of A.phrasesBySize)B.set(I.size,I.phrases.map(Q=>this.deserializeRhythmicPhrase(Q)));return{band:A.band,phrases:A.phrases.map(I=>this.deserializeRhythmicPhrase(I)),phrasesBySize:B,phrasesWithVariation:A.phrasesWithVariation.map(I=>this.deserializeRhythmicPhrase(I))}}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 hN={minFrequency:80,maxFrequency:1e3,frameSize:2048,hopSize:512,voicingThreshold:.2,transitionPenalty:.5,selfTransitionProbability:.99,yinThreshold:.4,targetSampleRate:44100},ld=69,Dd=440,lN=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];class Wo{constructor(A={}){if(this.states=[],this.transitionMatrix=[],this.config={...hN,...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,I=this.frequencyToMidi(A),Q=this.frequencyToMidi(B);this.states=[];for(let E=I;E<=Q;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 I=0;I<A;I++){B[I]=[];for(let Q=0;Q<A;Q++)B[I][Q]=this.transitionProbability(I,Q)}return B}transitionProbability(A,B){const{selfTransitionProbability:I,transitionPenalty:Q}=this.config,i=this.states.length-1;if(A===B)return Math.log(I);if(A===i||B===i)return Math.log((1-I)*.1);const e=this.states[A].midiNote,a=this.states[B].midiNote,C=Math.abs(a-e),o=(1-I)*Math.exp(-Q*C);return Math.log(o)}frequencyToMidi(A){return ld+12*Math.log2(A/Dd)}midiToFrequency(A){return Dd*Math.pow(2,(A-ld)/12)}midiToNoteName(A){const B=Math.floor(A/12)-1,I=Math.round(A)%12;return`${lN[I]}${B}`}detect(A){const I=XQ(A,this.config.targetSampleRate).data,Q=this.config.targetSampleRate,{frameSize:E,hopSize:i}=this.config,e=Math.floor((I.length-E)/i)+1,a=i/Q,C=[],o=[];for(let n=0;n<e;n++){const r=n*i,c=I.slice(r,r+E),{filtered:G,all:D}=this.analyzeFrame(c,Q);C.push(G),o.push(D)}const t=this.viterbiDecode(C),s=[];for(let n=0;n<e;n++){const r=t[n],c=this.states[r],G=C[n],D=o[n],h={timestamp:n*a,frequency:c.frequency,probability:this.getFrameProbability(r,G),isVoiced:c.frequency>0,midiNote:c.frequency>0?c.midiNote:null,noteName:c.frequency>0?this.midiToNoteName(c.midiNote):null};D.length>1&&(h.alternativeHypotheses=D.slice(0,5).map(w=>({frequency:w.frequency,probability:w.probability}))),s.push(h)}return s}detectSignal(A,B){const{frameSize:I,hopSize:Q}=this.config,E=Math.floor((A.length-I)/Q)+1,i=Q/B,e=[],a=[];for(let t=0;t<E;t++){const s=t*Q,n=A.slice(s,s+I),{filtered:r,all:c}=this.analyzeFrame(n,B);e.push(r),a.push(c)}const C=this.viterbiDecode(e),o=[];for(let t=0;t<E;t++){const s=C[t],n=this.states[s],r=e[t],c=a[t],G={timestamp:t*i,frequency:n.frequency,probability:this.getFrameProbability(s,r),isVoiced:n.frequency>0,midiNote:n.frequency>0?n.midiNote:null,noteName:n.frequency>0?this.midiToNoteName(n.midiNote):null};c.length>1&&(G.alternativeHypotheses=c.slice(0,5).map(D=>({frequency:D.frequency,probability:D.probability}))),o.push(G)}return o}detectSignalRaw(A,B){const{frameSize:I,hopSize:Q,voicingThreshold:E}=this.config,i=Math.floor((A.length-I)/Q)+1,e=Q/B,a=[];let C=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 n=s*Q,r=A.slice(n,n+I),{filtered:c,all:G}=this.analyzeFrame(r,B),D=s*e;if(c.length>0){C++;const h=c[0].probability;if(h<.1?t.below01++:h<.2?t.b01_02++:h<.3?t.b02_03++:h<.4?t.b03_04++:h<.5?t.b04_05++:t.above05++,h>=E){const w=c[0],y=Math.round(this.frequencyToMidi(w.frequency)),R={timestamp:D,frequency:w.frequency,probability:w.probability,isVoiced:!0,midiNote:y,noteName:this.midiToNoteName(y)};G.length>1&&(R.alternativeHypotheses=G.slice(0,5).map(Y=>({frequency:Y.frequency,probability:Y.probability}))),a.push(R)}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:C,framesWithNoCandidates:o,candidateRate:(C/i*100).toFixed(1)+"%",voicingThreshold:E,probBuckets:t}),a}detectAt(A,B,I){const{frameSize:Q,hopSize:E}=this.config,i=Math.round(I*B),e=Math.max(0,i-Math.floor(Q/2)),a=Math.min(A.length,e+Q);if(a-e<Q)return{timestamp:I,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null};const C=A.slice(e,a),{filtered:o,all:t}=this.analyzeFrame(C,B);if(o.length===0)return{timestamp:I,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null};const s=o[0],n=Math.round(this.frequencyToMidi(s.frequency)),r={timestamp:I,frequency:s.frequency,probability:s.probability,isVoiced:s.probability>=this.config.voicingThreshold,midiNote:n,noteName:this.midiToNoteName(n)};return t.length>1&&(r.alternativeHypotheses=t.slice(0,5).map(c=>({frequency:c.frequency,probability:c.probability}))),r}analyzeFrame(A,B){const{minFrequency:I,maxFrequency:Q,yinThreshold:E}=this.config,i=Math.ceil(B/I),e=Math.max(2,Math.floor(B/Q)),a=Math.min(i,Math.floor(A.length/2)),C=this.computeDifferenceFunction(A,a),o=this.computeCMNDF(C,e,a),t=[];for(let r=e+1;r<a-1;r++)if(o[r]<o[r-1]&&o[r]<o[r+1]&&o[r]<E){const c=this.parabolicInterpolation(o,r),G=B/c,D=1-o[r];G>=I&&G<=Q&&t.push({lag:c,frequency:G,probability:D})}if(t.sort((r,c)=>c.probability-r.probability),t.length===0)return{filtered:[],all:[]};const s=[],n=t[0].probability;for(const r of t){let c=!1;for(const G of t){if(G.frequency<=r.frequency||G.probability<n*.9)continue;const D=G.frequency/r.frequency,h=Math.round(D),w=Math.abs(D-h);if(h>=2&&h<=5&&w<.1){c=!0;break}}c||s.push(r)}return s.length===0&&t.length>0&&s.push(t[0]),{filtered:s,all:t}}computeDifferenceFunction(A,B){const I=A.length,Q=new Float32Array(B+1);Q[0]=0;for(let E=1;E<=B;E++){let i=0;for(let e=0;e<I-E;e++){const a=A[e]-A[e+E];i+=a*a}Q[E]=i}return Q}computeCMNDF(A,B,I){const Q=new Float32Array(A.length);Q[0]=1;let E=0;for(let i=1;i<=I;i++)E+=A[i],Q[i]=A[i]*i/E;return Q}parabolicInterpolation(A,B){if(B<=0||B>=A.length-1)return B;const I=A[B-1],Q=A[B],E=A[B+1],i=(E-I)/(2*(2*Q-I-E));return Math.max(B-1,Math.min(B+1,B+i))}getFrameProbability(A,B){const Q=this.states.length-1;if(A===Q)return B.length===0?1:1-B[0].probability;const E=this.states[A].frequency;let i=0;for(const e of B)Math.abs(e.frequency-E)/E<.05&&(i=Math.max(i,e.probability));return i}viterbiDecode(A){const B=A.length,I=this.states.length;if(B===0)return[];const Q=[];Q[0]=[];for(let a=0;a<I;a++){const C=this.priorLogProbability(a,A[0]);Q[0][a]={logProbability:C,previousState:-1}}for(let a=1;a<B;a++){Q[a]=[];for(let C=0;C<I;C++){const o=this.observationLogProbability(C,A[a]);let t=0,s=-1/0;for(let n=0;n<I;n++){const r=this.transitionMatrix[n][C],c=Q[a-1][n].logProbability+r;c>s&&(s=c,t=n)}Q[a][C]={logProbability:s+o,previousState:t}}}const E=new Array(B);let i=0,e=Q[B-1][0].logProbability;for(let a=1;a<I;a++)Q[B-1][a].logProbability>e&&(e=Q[B-1][a].logProbability,i=a);E[B-1]=i;for(let a=B-2;a>=0;a--)E[a]=Q[a+1][E[a+1]].previousState;return E}priorLogProbability(A,B){const I=this.states.length,Q=I-1,E=Math.log(.7/(I-1)),i=Math.log(.3);return A===Q?i+this.observationLogProbability(A,B):E+this.observationLogProbability(A,B)}observationLogProbability(A,B){const Q=this.states.length-1;if(A===Q){if(B.length===0)return Math.log(.9);const e=B[0].probability;return Math.log(1-e*.8)}const E=this.states[A].frequency;let i=0;for(const e of B){const a=e.frequency/E,C=Math.abs(a-1);if(C<.05){const o=1-C/.05*.2,t=e.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=e.probability*.4;s>i&&(i=s)}}}return Math.log(i===0?.01:i)}}const Xi="https://arweave.net/_HoMwkbF0JUamTiVGWNnCCC5yDjcPry-ENhzN6Xn3U0/model.json",dd={algorithm:"pitch_melodia",minFrequency:80,maxFrequency:2e4,frameSize:2048,hopSize:128,targetSampleRate:44100,crepeModelUrl:Xi},DN=69,dN=440,wN=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];class zQ{constructor(A){this.essentiaWASM=null,this.algorithms=null,this.crepeModel=null,this.initialized=!1,this.resolvedUrlCache=new Map,this.config={...dd,...A}}static async create(A={}){const B={...dd,...A};B.resolveUrl||(B.resolveUrl=TA.resolveUrl.bind(TA));const I=new zQ(B);return await I.initializeEssentia(),B.algorithm==="pitch_crepe"&&await I.loadCrepeModel(B.crepeModelUrl),I}getConfig(){return{...this.config}}async initializeEssentia(){if(this.initialized)return;const B=(await Promise.resolve().then(()=>Mb)).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 xI.getOrFetchGraphModel(IB,A,{resolveUrl:this.config.resolveUrl,invalidateUrlCache:I=>TA.invalidateCacheForUrl(I),maxRetries:3,baseDelayMs:1e3});else{const I=await this.resolveUrlWithCache(A);let Q=null;for(let E=0;E<3;E++)try{this.crepeModel=await IB.loadGraphModel(I);break}catch(i){Q=i;const e=String(i).toLowerCase();if(!(e.includes("fetch")||e.includes("network")||e.includes("timeout")||e.includes("failed to fetch")||e.includes("networkerror"))||E===2)throw i;const C=1e3*Math.pow(2,E);console.warn(`[EssentiaPitchDetector] CREPE model load failed (attempt ${E+1}/3), retrying in ${C}ms...`,{originalUrl:A,resolvedUrl:I,error:String(i)}),await new Promise(o=>setTimeout(o,C))}if(!this.crepeModel)throw new Error(`Failed to load CREPE model from ${A}: ${Q?.message??String(Q)}`)}const B=IB.zeros([1,1024]);IB.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 I=this.essentiaWASM.arrayToVector(A),Q=this.algorithms.PredominantPitchMelodia(I,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(Q.pitch)),i=Array.from(this.essentiaWASM.vectorToArray(Q.pitchConfidence)),e=this.config.hopSize/B;return this.mapSingleF0(E,i,e)}runPitchMelodia(A,B){const I=this.essentiaWASM.arrayToVector(A),Q=this.algorithms.PitchMelodia(I,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(Q.pitch)),i=Array.from(this.essentiaWASM.vectorToArray(Q.pitchConfidence)),e=this.config.hopSize/B;return this.mapSingleF0(E,i,e)}runPitchYinProbabilistic(A,B){const I=this.essentiaWASM.arrayToVector(A),Q=this.algorithms.PitchYinProbabilistic(I,this.config.frameSize,this.config.hopSize,.1,"negative",!1,B),E=Array.from(this.essentiaWASM.vectorToArray(Q.pitch)),i=Array.from(this.essentiaWASM.vectorToArray(Q.voicedProbabilities)),e=this.config.hopSize/B;return E.map((a,C)=>{const o=C*e;if(a>0&&i[C]>.5){const s=Math.round(this.frequencyToMidi(a));return{timestamp:o,frequency:a,probability:i[C],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 I=this.essentiaWASM.arrayToVector(A),Q=this.algorithms.MultiPitchMelodia(I,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(Q.pitch,B)}runMultiPitchKlapuri(A,B){const I=this.essentiaWASM.arrayToVector(A),Q=this.algorithms.MultiPitchKlapuri(I,10,this.config.frameSize,.8,this.config.hopSize,1,40,this.config.maxFrequency,this.config.minFrequency,10,55,B);return this.mapMultiPitch(Q.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 I=16e3,Q=1024,E=256,i=this.resampleSignal(A,B,I),e=Math.floor((i.length-Q)/E)+1,a=E/I,C=32.7,o=[];for(let t=0;t<e;t++){const s=t*E,n=i.slice(s,s+Q),r=t*a;let c;try{const D=IB.tidy(()=>{const R=IB.tensor(n,[1,Q]);return this.crepeModel.execute(R).dataSync().slice()});let h=0,w=0,y=0;for(let R=0;R<360;R++){const Y=D[R];h+=R*10*Y,w+=Y,Y>y&&(y=Y)}if(w>0&&y>.3){const R=h/w,Y=C*Math.pow(2,R/1200),k=Math.round(this.frequencyToMidi(Y));c={timestamp:r,frequency:Y,probability:y,isVoiced:!0,midiNote:k,noteName:this.midiToNoteName(k)}}else c={timestamp:r,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}}catch(G){console.error(`[EssentiaPitchDetector] CREPE inference error at frame ${t}:`,G),c={timestamp:r,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}}o.push(c)}return o}mapSingleF0(A,B,I){return A.map((Q,E)=>{const i=E*I;if(Q>0){const e=Math.round(this.frequencyToMidi(Q));return{timestamp:i,frequency:Q,probability:B[E]??0,isVoiced:!0,midiNote:e,noteName:this.midiToNoteName(e)}}return{timestamp:i,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}})}mapMultiPitch(A,B){const I=A.size(),Q=this.config.hopSize/B,E=[];for(let i=0;i<I;i++){const e=A.get(i),C=Array.from(this.essentiaWASM.vectorToArray(e)).filter(t=>t>0).sort((t,s)=>t-s),o=i*Q;if(C.length>0){const t=C[0],s=Math.round(this.frequencyToMidi(t)),n=C.slice(1).map(r=>({frequency:r,probability:1}));E.push({timestamp:o,frequency:t,probability:1,isVoiced:!0,midiNote:s,noteName:this.midiToNoteName(s),...n.length>0?{alternativeHypotheses:n}:{}})}else E.push({timestamp:o,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null})}return E}resampleSignal(A,B,I){if(B===I)return A;const Q=B/I,E=Math.round(A.length/Q),i=new Float32Array(E);for(let e=0;e<E;e++){const a=e*Q,C=Math.floor(a),o=Math.min(C+1,A.length-1),t=a-C;i[e]=A[C]*(1-t)+A[o]*t}return i}frequencyToMidi(A){return DN+12*Math.log2(A/dN)}midiToNoteName(A){const B=Math.floor(A/12)-1,I=Math.round(A)%12;return`${wN[I]}${B}`}}const wd={targetSampleRate:44100,pitchDetector:{},pitchAlgorithm:"pitch_melodia",crepeModelUrl:Xi};class Fd{constructor(A={}){this.essentiaDetector=null,this.config={...wd,...A,pitchDetector:{...wd.pitchDetector,...A.pitchDetector}},this.fullSpectrumDetector=new Wo({...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 I=this.config.targetSampleRate,E=XQ(B,I).data;let i,e;this.config.pitchAlgorithm==="pyin_legacy"?(i=this.fullSpectrumDetector.detectSignalRaw(E,I),e=this.fullSpectrumDetector.getConfig().hopSize/I):(this.essentiaDetector||(this.essentiaDetector=await zQ.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,I),e=this.essentiaDetector.getConfig().hopSize/I),console.debug("[PitchBeatLinker] Full-spectrum analysis:",{detector:this.config.pitchAlgorithm==="pyin_legacy"?"pYIN":`essentia/${this.config.pitchAlgorithm}`,totalFrames:i.length,voicedFrames:i.filter(C=>C.isVoiced).length,signalLength:E.length,signalSampleRate:I});const a=[];for(const C of A.beats){const o=C.detectedTimestamp??C.timestamp,t=Math.round(o/e);let s=null,n=1/0,r=0;for(let c=0;c<i.length;c++){const G=i[c];if(!G.isVoiced)continue;const D=Math.abs(c-t);(D<n||D===n&&G.probability>r)&&(n=D,r=G.probability,s=G)}a.push({beatIndex:C.beatIndex,timestamp:C.timestamp,band:C.sourceBand,pitch:s,direction:"none",intervalFromPrevious:0})}return a}deriveVariantPitches(A,B){const I=[],Q=new Map;for(const E of B){const i=Math.round(E.timestamp*1e3);Q.set(i,E)}for(const E of A.beats){const i=Math.round(E.timestamp*1e3);let e=Q.get(i);if(!e)for(let a=-2;a<=2&&(e=Q.get(i+a),!e);a++);e?I.push({beatIndex:E.beatIndex,timestamp:E.timestamp,band:E.sourceBand,pitch:e.pitch,direction:e.direction,intervalFromPrevious:e.intervalFromPrevious,intervalCategory:e.intervalCategory}):I.push({beatIndex:E.beatIndex,timestamp:E.timestamp,band:E.sourceBand,pitch:null,direction:"none",intervalFromPrevious:0})}return I}deriveAllVariantPitches(A,B){return{easy:this.deriveVariantPitches(A.easy,B),medium:this.deriveVariantPitches(A.medium,B),hard:this.deriveVariantPitches(A.hard,B)}}}const FN={maxTimeGapForConsecutive:.5};function Md(g){return g===0?"unison":g<=2?"small":g<=4?"medium":g<=7?"large":"very_large"}function MN(g,A){return Math.abs(g-A)}function RN(g,A){return g===null||A===null?"none":g>A?"up":g<A?"down":"stable"}function yN(g){if(g.length===0)return"stable";let A=0,B=0,I=0;for(const e of g)e.direction==="up"?A++:e.direction==="down"?B++:I++;if(A===0&&B===0)return"stable";const Q=A-B,i=(A+B+I)*.2;return Math.abs(Q)<=i?"mixed":A>B?"ascending":B>A?"descending":"stable"}function Rd(g){const A=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],B=Math.floor(g/12)-1,I=g%12;return`${A[I]}${B}`}class uN{constructor(A={}){this.config={...FN,...A}}getConfig(){return{...this.config}}analyze(A){const B=this.analyzeBandPitches(A),{directionStats:I,intervalStats:Q,metadata:E}=this.calculateStatistics(B),i=this.buildMelodyContour(B);return{pitchByBeat:B,melodyContour:i,directionStats:I,intervalStats:Q,metadata:E}}analyzeBandPitches(A){if(A.length===0)return[];const B=[];for(let I=0;I<A.length;I++){const Q=A[I],E=I>0?A[I-1]:null,i=E!==null&&Q.timestamp-E.timestamp<=this.config.maxTimeGapForConsecutive;let e,a,C;if(!i||!E||!E.pitch||!Q.pitch)e="none",a=0,C="unison";else{const o=Q.pitch.midiNote,t=E.pitch.midiNote;o===null||t===null?(e="none",a=0,C="unison"):(e=RN(o,t),a=MN(o,t),C=Md(a))}B.push({...Q,direction:e,intervalFromPrevious:a,intervalCategory:C})}return B}buildMelodyContour(A){const B=A.filter(n=>n.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 I=B.map(n=>n.pitch?.midiNote).filter(n=>n!==null);if(I.length===0)return{segments:[],direction:"stable",range:{minNote:"N/A",maxNote:"N/A",semitones:0},shortTermDirection:"stable",mediumTermDirection:"stable",longTermDirection:"stable"};const Q=Math.min(...I),E=Math.max(...I),i=Rd(Q),e=Rd(E),a=this.buildSegments(B),C=yN(a),o=this.calculateTimeWindowDirection(A,1,2),t=this.calculateTimeWindowDirection(A,4,8),s=this.calculateTimeWindowDirection(A,16,1/0);return{segments:a,direction:C,range:{minNote:i,maxNote:e,semitones:E-Q},shortTermDirection:o,mediumTermDirection:t,longTermDirection:s}}calculateTimeWindowDirection(A,B,I){if(A.length===0||B<1)return"stable";const Q=Math.min(I,Math.max(B,A.length)),E=A.slice(-Q);if(E.length===0)return"stable";let i=0,e=0,a=0;for(const C of E)C.direction==="up"?i++:C.direction==="down"?e++:C.direction==="stable"&&a++;return this.determineOverallDirectionFromCounts(i,e,a)}determineOverallDirectionFromCounts(A,B,I){const Q=A+B+I;if(Q===0)return"stable";const E=Q*.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 I=null;for(const Q of A){const E=Q.direction;if(E==="none"){I&&(B.push({startTime:I.startTime,endTime:I.endTime,startPitch:I.startPitch,endPitch:I.endPitch,direction:I.direction,interval:Math.abs(I.endMidi-I.startMidi)}),I=null);continue}if(!I||I.direction!==E){I&&B.push({startTime:I.startTime,endTime:I.endTime,startPitch:I.startPitch,endPitch:I.endPitch,direction:I.direction,interval:Math.abs(I.endMidi-I.startMidi)});const i=Q.pitch?.noteName??"N/A",e=Q.pitch?.midiNote??60;I={startTime:Q.timestamp,endTime:Q.timestamp,startPitch:i,endPitch:i,direction:E,startMidi:e,endMidi:e}}else{const i=Q.pitch?.midiNote??I.endMidi,e=Q.pitch?.noteName??I.endPitch;I.endTime=Q.timestamp,I.endPitch=e,I.endMidi=i}}return I&&B.push({startTime:I.startTime,endTime:I.endTime,startPitch:I.startPitch,endPitch:I.endPitch,direction:I.direction,interval:Math.abs(I.endMidi-I.startMidi)}),B}calculateStatistics(A){const B={up:0,down:0,stable:0,none:0},I={unison:0,small:0,medium:0,large:0,very_large:0};let Q=0,E=0;for(const i of A)i.pitch?.isVoiced&&Q++,B[i.direction]++,i.direction!=="none"&&E++,i.intervalCategory&&I[i.intervalCategory]++;return{directionStats:B,intervalStats:I,metadata:{totalBeats:A.length,voicedBeats:Q,directionCalculatedBeats:E}}}}const mN={algorithm:"pitch_melodia",minFrequency:80,maxFrequency:2e4,sampleRate:44100,hopSize:1024,crepeModelUrl:Xi,resolveUrl:TA.resolveUrl.bind(TA),includeContour:!0,onProgress:void 0},SN=69,bN=440,pN=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];class YN{constructor(A={}){this.config={...mN,...A}}getConfig(){return{...this.config}}async analyze(A){const{onProgress:B}=this.config;B?.("fetching",0);const{signal:I,sampleRate:Q,duration:E}=await this.fetchAndDecodeAudio(A);B?.("fetching",1),B?.("detecting",0);const i=this.resolveDefaults(this.config),e=await this.detectPitch(I,Q,i);B?.("detecting",1);const a=this.computeSummary(e);let C,o,t;if(this.config.includeContour!==!1){const s=this.computeContour(e);C=s.contour,o=s.directionStats,t=s.intervalStats}return{pitchResults:e,contour:C,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,I=await fetch(B);if(!I.ok)throw new Error(`Failed to fetch audio: ${I.statusText}`);const Q=await I.arrayBuffer(),E=globalThis.AudioContext||globalThis.window?.AudioContext;if(!E)throw new Error("AudioContext not available in this environment");const i=new E,e=await new Promise((C,o)=>{i.decodeAudioData(Q,C,o)}),a=new Float32Array(e.length);for(let C=0;C<e.numberOfChannels;C++){const o=e.getChannelData(C);for(let t=0;t<e.length;t++)a[t]+=o[t]/e.numberOfChannels}return{signal:a,sampleRate:e.sampleRate,duration:e.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,I){const Q=I.algorithm??"pitch_melodia";return Q==="pyin_legacy"?new Wo({minFrequency:I.minFrequency??80,maxFrequency:I.maxFrequency??1e3,targetSampleRate:I.sampleRate??44100,hopSize:I.hopSize??1024}).detectSignal(A,B):(await zQ.create({algorithm:Q,minFrequency:I.minFrequency??80,maxFrequency:I.maxFrequency??2e4,targetSampleRate:I.sampleRate??44100,hopSize:I.hopSize??1024,crepeModelUrl:I.crepeModelUrl,resolveUrl:I.resolveUrl})).detectSignal(A,B)}computeSummary(A){const B=A.length,I=A.filter(w=>w.isVoiced&&w.frequency>0),Q=I.length;if(Q===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=I.map(w=>w.frequency),i=[...E].sort((w,y)=>w-y),e=E.reduce((w,y)=>w+y,0)/E.length,a=Math.floor(i.length/2),C=i.length%2!==0?i[a]:(i[a-1]+i[a])/2,o=i[0],t=i[i.length-1],s=this.frequencyToMidi(o),n=this.frequencyToMidi(t),r=Math.abs(n-s),c=this.midiToNoteName(Math.round(s)),G=this.midiToNoteName(Math.round(n)),D=new Map;for(const w of I)w.noteName&&D.set(w.noteName,(D.get(w.noteName)??0)+1);const h=Array.from(D.entries()).map(([w,y])=>({note:w,count:y,percentage:y/Q*100})).sort((w,y)=>y.count-w.count);return{voicingRatio:Q/B,averageFrequency:e,medianFrequency:C,minFrequency:o,maxFrequency:t,pitchRangeSemitones:r,lowestNote:c,highestNote:G,noteDistribution:h,totalFrames:B,voicedFrames:Q}}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 I=B.map(D=>D.midiNote).filter(D=>D!==null),Q=Math.min(...I),E=Math.max(...I),i=this.midiToNoteName(Q),e=this.midiToNoteName(E),a={up:0,down:0,stable:0,none:0},C={unison:0,small:0,medium:0,large:0,very_large:0},o=[];let t=null,s=null;for(const D of B){const h=D.midiNote;if(h===null){a.none++;continue}if(s===null){s=h;continue}let w;const y=Math.abs(h-s);h>s?(w="up",a.up++):h<s?(w="down",a.down++):(w="stable",a.stable++);const R=Md(y);C[R]++,!t||t.direction!==w?(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(h),direction:w,startMidi:s,endMidi:h}):(t.endTime=D.timestamp,t.endNote=this.midiToNoteName(h),t.endMidi=h),s=h}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 n=this.determineOverallDirection(o),r=this.calculateTimeWindowDirection(A,1,2),c=this.calculateTimeWindowDirection(A,4,8),G=this.calculateTimeWindowDirection(A,16,1/0);return{contour:{direction:n,range:{minNote:i,maxNote:e,semitones:E-Q},segments:o,shortTermDirection:r,mediumTermDirection:c,longTermDirection:G},directionStats:a,intervalStats:C}}determineOverallDirection(A){if(A.length===0)return"stable";let B=0,I=0,Q=0;for(const a of A)a.direction==="up"?B++:a.direction==="down"?I++:Q++;if(B===0&&I===0)return"stable";const E=B-I,e=(B+I+Q)*.2;return Math.abs(E)<=e?"mixed":B>I?"ascending":I>B?"descending":"stable"}calculateTimeWindowDirection(A,B,I){const Q=A.filter(t=>t.isVoiced&&t.midiNote!==null);if(Q.length===0||B<1)return"stable";const E=Math.min(I,Math.max(B,Q.length)),i=Q.slice(-E);if(i.length===0)return"stable";let e=0,a=0,C=0,o=null;for(const t of i){const s=t.midiNote;s!==null&&(o!==null&&(s>o?e++:s<o?a++:C++),o=s)}return this.determineOverallDirectionFromCounts(e,a,C)}determineOverallDirectionFromCounts(A,B,I){const Q=A+B+I;if(Q===0)return"stable";const E=Q*.2,i=A-B;return Math.abs(i)<=E?"mixed":A>B?"ascending":B>A?"descending":"stable"}frequencyToMidi(A){return SN+12*Math.log2(A/bN)}midiToNoteName(A){const B=Math.floor(A/12)-1,I=Math.round(A)%12;return`${pN[I]}${B}`}}const UN=[{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}],fN=[{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}],kN=[{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}],ZN=[{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}],NN=[{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}],WN=[{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}],HN=[{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}],JN=[{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}],xN=[{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}],qN=[{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}],LN=[...UN,...fN,...kN,...ZN,...NN],VN=[...WN,...HN,...JN,...xN,...qN];function yd(g,A){const B=new Map,I=["basic","roll","stream","jump","chord","transition"];for(const E of I){const i=A.filter(e=>e.category===E);i.length>0&&B.set(E,i)}const Q=new Map;for(let E=1;E<=10;E++){const i=A.filter(e=>e.difficulty===E);i.length>0&&Q.set(E,i)}return{controllerMode:g,patterns:A,byCategory:B,byDifficulty:Q}}const Ho=yd("ddr",LN),Jo=yd("guitar_hero",VN);function vN(g){return g==="ddr"?Ho:Jo}function XN(g,A){return g.byCategory.get(A)??[]}function KN(g,A=1,B=10){const I=[];for(let Q=A;Q<=B;Q++){const E=g.byDifficulty.get(Q);E&&I.push(...E)}return I}function zN(g,A){return g.patterns.filter(B=>A.every(I=>B.tags.includes(I)))}function TN(g,A){return g.patterns.filter(B=>B.keys.length===A)}function ON(g,A){const B=A?g.patterns.filter(A):g.patterns;if(B.length===0)return;const I=Math.floor(Math.random()*B.length);return B[I]}function jN(g,A){return g.patterns.find(B=>B.id===A)}function PN(g){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 I=0,Q=1/0,E=0;for(const i of g.patterns)A[i.category]++,B[i.difficulty]++,I+=i.keys.length,Q=Math.min(Q,i.keys.length),E=Math.max(E,i.keys.length);return{totalPatterns:g.patterns.length,byCategory:A,byDifficulty:B,averageKeyCount:g.patterns.length>0?I/g.patterns.length:0,minKeys:Q===1/0?0:Q,maxKeys:E}}const ud={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"}},_N={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"}},md={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}},$N={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 Sd(g){return g.intervalCategory??"small"}function AW(g,A,B){const I=A??"left";if(g.direction==="stable"||g.intervalCategory==="unison")return I;if(B==="easy"){const e=_N[I];return g.direction==="up"?e.ascending:e.descending}const Q=ud[I],E=g.direction==="up"?"ascending":"descending",i=Sd(g);return Q[E][i]}function BW(g,A,B){const I=A??3;if(g.direction==="stable"||g.intervalCategory==="unison")return I;if(B==="easy"){const e=$N[I];return g.direction==="up"?e.ascending:e.descending}const Q=md[I],E=g.direction==="up"?"ascending":"descending",i=Sd(g);return Q[E][i]}function gW(g,A,B,I){const Q=new Map;if(A)for(const a of A){const C=Math.round(a.timestamp*1e3);Q.set(C,a)}const E=[],i=[];let e=null;for(const a of g){const C=Math.round(a.timestamp*1e3);let o=null;for(let n=-2;n<=2&&(o=Q.get(C+n)??null,!o);n++);let t=null,s=0;o&&o.direction!=="none"&&(t=B==="ddr"?AW(o,e,I):BW(o,e,I),s=o.pitch?.probability??.5),E.push(t),i.push(s),e=t}return{pitchKeys:E,probabilities:i}}function IW(g){const A=[];let B=-1;for(let I=0;I<=g.length;I++){const Q=I<g.length&&g[I]===null;if(Q&&B===-1)B=I;else if(!Q&&B!==-1){const E=B>0?g[B-1]:null,i=I<g.length?g[I]:null;A.push({startIndex:B,endIndex:I,length:I-B,previousKey:E,nextKey:i}),B=-1}}return A}function Ki(g,A,B,I,Q){if(g.keys.length===0||B+g.keys.length>A.length)return!1;const E=g.keys[0],i=g.keys[g.keys.length-1];if(I!==null&&E===I)return!1;if(Q!==null){if(typeof i=="string"&&typeof Q=="string"&&!TQ[i]?.includes(Q)&&i!==Q)return!1;if(typeof i=="number"&&typeof Q=="number"){if(I!==null&&typeof I=="number"){if(!(I<Q&&i>=I&&i<=Q||I>Q&&i<=I&&i>=Q)&&i!==Q)return!1}else if(Math.abs(i-Q)>1)return!1}}return!0}function QW(g,A,B,I,Q){const E=[],i=A.filter(s=>s.difficulty<=B&&s.keys.length>0);i.sort((s,n)=>n.keys.length-s.keys.length);const e=i[0]?.controllerMode??"ddr";let a=0,C=g.previousKey,o=null,t=null;for(;a<g.length;){const s=g.length-a;let n;const r=i.filter(c=>c.keys.length===s);if(n=xo(r,g,a,C,g.nextKey,o,t,I,Q),!n){const c=i.filter(G=>G.keys.length<=s);n=xo(c,g,a,C,null,o,t,I,Q)}if(!n){const c=i.filter(G=>G.keys.length<=s);n=xo(c,g,a,C,null,null,null,null,Q)}if(n)E.push({pattern:n,startIndex:g.startIndex+a,filledLength:n.keys.length}),C=n.keys[n.keys.length-1],o=n.id,t=n.category,a+=n.keys.length;else{const c=a===g.length-1?g.nextKey:null,G=bd(C,c);E.push({pattern:{id:"__interpolated__",name:"Interpolated",controllerMode:e,keys:[G],measures:0,tags:["interpolated"],category:"transition",difficulty:1},startIndex:g.startIndex+a,filledLength:1}),C=G,a++}}return E}function xo(g,A,B,I,Q,E,i,e,a=Math.random){const C=g.filter(n=>Ki(n,A,B,I,Q)&&n.id!==E&&n.category!==i&&!e?.has(n.id));if(C.length>0)return zi(C,a);const o=g.filter(n=>Ki(n,A,B,I,Q)&&n.id!==E&&!e?.has(n.id));if(o.length>0)return zi(o,a);const t=g.filter(n=>Ki(n,A,B,I,Q)&&n.id!==E);if(t.length>0)return zi(t,a);const s=g.filter(n=>Ki(n,A,B,I,Q));if(s.length>0)return zi(s,a)}function zi(g,A=Math.random){const B=g[0].keys.length,I=g.filter(Q=>Q.keys.length===B);return I[Math.floor(A()*I.length)]}function EW(g,A,B){const I=g.length,Q=[...g],E=new Array(I).fill(void 0);for(let i=0;i<A.length;i++){const e=B[i];for(const a of e)for(let C=0;C<a.filledLength;C++){const o=a.startIndex+C;if(o>=I)break;Q[o]=a.pattern.keys[C],E[o]=a.pattern.id}}for(let i=0;i<I;i++)if(Q[i]===null){const e=i>0?Q[i-1]:null,a=i<I-1?Q[i+1]:null;Q[i]=bd(e,a)}return{keys:Q,patternIds:E}}function iW(g,A){const B=[];if(A<=0||g.length===0)return{positions:B};let I=1;const Q=g[0];for(let E=1;E<g.length;E++)g[E]===Q?(I++,I>A&&B.push(E)):I=1;return{positions:B}}function eW(g,A,B,I=Math.random){const Q=A.filter(e=>e.difficulty<=B);if(Q.length===0)return g;const E=Q.filter(e=>e.keys[0]!==g),i=E.length>0?E:Q;return i[Math.floor(I()*i.length)].keys[0]}const TQ={up:["left","right"],down:["left","right"],left:["up","down"],right:["up","down"]};function bd(g,A){if(g===null)return A===null?typeof A=="string"?"left":3:typeof A=="string"?TQ[A][0]:Math.max(1,A-1);if(A===null)return g;if(typeof g=="string"&&typeof A=="string"){const B=g,I=A;if(B===I)return g;if(TQ[B].includes(I))return A;const E=TQ[B],i=TQ[I];for(const e of E)if(i.includes(e))return e;return E[0]}if(typeof g=="number"&&typeof A=="number"){const B=g,I=A;return B===I?g:I>B?Math.min(5,B+1):Math.max(1,B-1)}return g}class Ti{constructor(A){this.config=rC(A);const B=ah(this.config);if(!B.valid)throw new Error(`Invalid button mapping config: ${B.errors.join(", ")}`)}seededRandom(A){return this.config.seed?mg(Pg(this.config.seed,A)):Math.random()}getConfig(){return{...this.config}}mapVariant(A,B,I){const Q=this.mapButtons(A,I,A.difficulty),E=this.buildMetadata(Q,I),i=new Map,e=new Map,a=new Map;for(const C of Q)i.set(C.beatIndex,String(C.key)),e.set(C.beatIndex,C.source),a.set(C.beatIndex,C.patternId);return{variant:A,rhythmMetadata:B,buttonMetadata:E,keyAssignments:i,mappingSources:e,mappingPatternIds:a}}map(A,B,I){const Q=A.difficultyVariants[B];return this.mapVariant(Q,A.metadata,I)}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,I){const Q=A.beats;if(this.config.controllerMode==="tap")return Q.map((h,w)=>({beatIndex:w,timestamp:h.timestamp,key:"tap",source:"pattern",patternId:void 0,probability:void 0}));const E=[],i=this.getMaxPatternDifficulty(I);let e=0;const{pitchKeys:a,probabilities:C}=gW(Q,B,this.config.controllerMode,I),o=this.classifyPitchVsPattern(a,C,this.config.pitchInfluenceWeight),t=a.map((h,w)=>h!==null&&o[w]?h:null),s=this.config.controllerMode==="ddr"?Ho.patterns:Jo.patterns,n=IW(t),r=new Set,c=n.map((h,w)=>{const y=QW(h,s,i,r,()=>this.seededRandom(`run:${w}:pick:${e++}`));for(const R of y)R.pattern.id!=="__interpolated__"&&r.add(R.pattern.id);return y}),{keys:G,patternIds:D}=EW(t,n,c);for(let h=0;h<Q.length;h++){const w=t[h]!==null;E.push({beatIndex:h,timestamp:Q[h].timestamp,key:G[h],source:w?"pitch":"pattern",patternId:w?void 0:D[h],probability:C[h]})}return this.config.consecutiveSameKeyLimit>0&&this.applyConsecutiveLimit(E,s,i),E}classifyPitchVsPattern(A,B,I){const Q=new Array(A.length).fill(!1),E=A.map((a,C)=>({index:C,probability:B[C],hasPitch:a!==null})).filter(a=>a.hasPitch);E.sort((a,C)=>a.probability-C.probability);const i=Math.floor(E.length*(1-I)),e=new Set(E.slice(0,i).map(a=>a.index));for(let a=0;a<A.length;a++)A[a]===null||e.has(a)?Q[a]=!1:Q[a]=!0;return Q}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,I){const Q=A.map(e=>e.key),E=this.config.consecutiveSameKeyLimit,{positions:i}=iW(Q,E);for(let e=0;e<i.length;e++){const a=i[e],C=eW(A[a].key,B,I,()=>this.seededRandom(`var:${a}:${e}`));C!==A[a].key&&(A[a].key=C,A[a].source="pattern",A[a].patternId="consecutive_limit_fix")}}buildMetadata(A,B){const I=new Set,Q=new Map;let E=0,i=0;const e=new Set;for(const r of A){const c=String(r.key);I.add(c),Q.set(c,(Q.get(c)??0)+1),r.source==="pitch"?E++:i++,r.patternId&&e.add(r.patternId)}let a,C,o;if(B&&B.length>0){a={up:0,down:0,stable:0,none:0},C={unison:0,small:0,medium:0,large:0,very_large:0},o={low:0,mid:0,high:0};for(const r of B)a[r.direction]++,r.intervalCategory&&C[r.intervalCategory]++,r.band&&o[r.band]++}const t=[];let s,n=0;for(let r=0;r<A.length;r++){const c=A[r].patternId;c&&c===s||(s&&t.push({patternId:s,startIndex:n,length:r-n}),s=c,n=r)}return s&&t.push({patternId:s,startIndex:n,length:A.length-n}),{controllerMode:this.config.controllerMode,keysUsed:Array.from(I),pitchInfluencedBeats:E,patternInfluencedBeats:i,patternsUsed:Array.from(e),buttonDistribution:Q,directionStats:a,intervalStats:C,bandStats:o,patternPlacements:t}}static getDDRTransitions(){return ud}static getGuitarHeroTransitions(){return md}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 Oi{convertToChartedBeatMap(A,B,I,Q,E,i){const e=[],a=[];for(let o=0;o<A.beats.length;o++){const t=A.beats[o],s=this.convertBeat(t,B,I.get(o),o,E?.get(o),i?.get(o));e.push(s),s.isDetected&&a.push(o)}const C=this.buildChartMetadata(A,Q,e,I);return{audioId:B.audioId,duration:B.duration,beats:e,detectedBeatIndices:a,downbeatConfig:B.downbeatConfig,quarterNoteInterval:B.quarterNoteInterval,bpm:B.quarterNoteBpm,chartMetadata:C}}convertWithOptions(A,B){const I={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()},Q={audioId:B.audioId,duration:B.duration,beats:[],detectedBeatIndices:[],quarterNoteInterval:B.quarterNoteInterval,quarterNoteBpm:60/B.quarterNoteInterval,downbeatConfig:B.downbeatConfig,originalMetadata:I};return this.convertToChartedBeatMap(A,Q,B.keyAssignments,B.metadata)}convertBeat(A,B,I,Q,E,i){const e=A.beatIndex,a=this.getParentBeat(B,e),C=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:C,isDownbeat:(a?.isDownbeat??!1)&&A.gridPosition===0,measureNumber:a?.measureNumber??0,intensity:A.intensity,confidence:s,requiredKey:I,quarterNoteIndex:e,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,I){const Q=A?.beatInMeasure??0;return oh(Q,B,I)}isBeatDetected(A){return A.quantizationError===void 0?!0:A.quantizationError<10}mapGridToSubdivision(A){return Ch(A)}calculateConfidence(A,B){return B?Math.min(1,.8+A.intensity*.2):.8}buildChartMetadata(A,B,I,Q){const E=B.pitchInfluencedBeats??0,i=this.getUniqueKeys(I);return this.getSubdivisionTypesUsed(I),{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 I of A)I.requiredKey!==void 0&&B.add(I.requiredKey);return Array.from(B).sort()}getSubdivisionTypesUsed(A){const B=new Set;for(const I of A)B.add(I.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,I,Q,E,i,e){const a=E??new Map;if(a.size===0&&I.keysUsed.length>0)for(let n=0;n<A.beats.length;n++)a.set(n,I.keysUsed[n%I.keysUsed.length]);const C=new Oi,o={difficulty:Q.difficulty,bandsAnalyzed:Q.bandsAnalyzed,transientsDetected:Q.transientsDetected,averageDensity:Q.averageDensity,naturalDifficulty:Q.naturalDifficulty},t=I.directionStats?{melodyRange:null,directionStats:I.directionStats,intervalStats:I.intervalStats??null}:null,s={difficulty:A.difficulty,keysUsed:I.keysUsed,pitchInfluencedBeats:I.pitchInfluencedBeats,patternsUsed:I.patternsUsed,rhythmMetadata:o,pitchMetadata:t,generatedAt:new Date().toISOString()};return C.convertToChartedBeatMap(A,B,a,s,i,e)}}const OQ={difficulty:"medium",controllerMode:"ddr",rhythm:{},buttons:{},enableCache:!0,cacheMaxAge:1800*1e3};class ji{constructor(A={}){this.cache=new Map,this.cacheHits=0,this.cacheMisses=0,this.options={...OQ,...A,rhythm:{...OQ.rhythm,...A.rhythm},buttons:{...OQ.buttons,...A.buttons}},this.buttonConfig=rC({...this.options.buttons,difficulty:this.options.difficulty,controllerMode:this.options.controllerMode,seed:this.options.seed})}getOptions(){return{...this.options}}generateCacheKey(A,B,I){return`${A}:${B}:${I}`}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 I=Date.now()-B.timestamp,Q=this.options.cacheMaxAge??OQ.cacheMaxAge;return I>Q?(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??OQ.cacheMaxAge;for(const[I,Q]of this.cache.entries())A-Q.timestamp>B&&this.cache.delete(I)}getCacheStats(){const A=[];for(const[B]of this.cache.entries()){const I=B.split(":")[1];A.includes(I)||A.push(I)}return{entryCount:this.cache.size,cachedPhases:A,hits:this.cacheHits,misses:this.cacheMisses}}isCached(A,B){const I=this.createConfigFingerprint(B),Q=this.generateCacheKey(A,B,I);return this.cache.has(Q)}getCacheHitRatio(){const A=this.cacheHits+this.cacheMisses;return A===0?0:this.cacheHits/A}async generate(A,B,I,Q){const E=(s,n,r)=>{I?.({stage:s,progress:n,message:r})};Q?.throwIfAborted();const i=B.audioId;E("rhythm",0,"Starting rhythm generation...");let e=null;if(this.options.cachedRhythm)e=this.options.cachedRhythm,E("rhythm",1,"Using pre-generated rhythm from store");else{const s=this.generateCacheKey(i,"rhythm",this.createConfigFingerprint("rhythm"));e=this.getFromCache(s),e?E("rhythm",1,"Rhythm loaded from cache"):(e=await this.generateRhythm(A,B,(n,r,c)=>{E("rhythm",r,`[${n}] ${c}`)},Q),this.setCache(s,e),E("rhythm",1,"Rhythm generation complete"))}Q?.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,e,(n,r)=>{E("pitch",n,r)}),this.setCache(s,a),E("pitch",1,"Pitch analysis complete"))}else E("pitch",1,"Pitch analysis skipped");Q?.throwIfAborted(),E("buttons",0,"Starting button mapping...");const C=this.mapButtons(e,a);E("buttons",1,"Button mapping complete"),Q?.throwIfAborted(),E("conversion",0,"Converting to playable chart...");const o=this.convertToChart(C,B);E("conversion",1,"Chart conversion complete"),Q?.throwIfAborted(),E("finalizing",0,"Finalizing level...");const t=this.buildLevel(o,C,e,a);return E("finalizing",1,"Level generation complete"),t}async generateAllDifficulties(A,B,I,Q){const E=["easy","medium","hard","natural"],i={easy:null,medium:null,hard:null,natural:null};Q?.throwIfAborted();const e=B.audioId;let a=null;if(this.options.cachedRhythm)a=this.options.cachedRhythm;else{const o=this.generateCacheKey(e,"rhythm",this.createConfigFingerprint("rhythm"));a=this.getFromCache(o),a||(a=await this.generateRhythm(A,B,void 0,Q),this.setCache(o,a))}Q?.throwIfAborted();let C=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const o=this.generateCacheKey(e,"pitch",this.createConfigFingerprint("pitch"));C=this.getFromCache(o),C||(C=await this.analyzePitch(A,a),this.setCache(o,C))}Q?.throwIfAborted();for(let o=0;o<E.length;o++){const t=E[o];I?.({stage:"buttons",progress:o/E.length,message:`Generating ${t} chart...`}),Q?.throwIfAborted();const s=new ji({...this.options,difficulty:t,buttons:{...this.options.buttons,difficulty:t}}),n=s.mapButtons(a,C),r=s.convertToChart(n,B),c=s.buildLevel(r,n,a,C);i[t]=c}return{easy:i.easy,medium:i.medium,hard:i.hard,natural:i.natural}}async generateAtDensity(A,B,I,Q,E){const i=(D,h,w)=>{Q?.({stage:D,progress:h,message:w})};E?.throwIfAborted();const e=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(e,"rhythm",this.createConfigFingerprint("rhythm"));a=this.getFromCache(D),a?i("rhythm",1,"Rhythm loaded from cache"):(a=await this.generateRhythm(A,B,(h,w,y)=>{i("rhythm",w,`[${h}] ${y}`)},E,!0),this.setCache(D,a),i("rhythm",1,"Rhythm generation complete"))}E?.throwIfAborted(),i("buttons",0,"Generating density-based variant...");const C=this.collectGridDecisions(a.analysis.quantizationResult),t=new vi({seed:this.options.seed}).generateAtDensity(a.composite,I,B,a.analysis.phraseAnalysis,C);i("buttons",.3,"Density variant generated");let s=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const D=this.generateCacheKey(e,"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,(h,w)=>{i("pitch",h,w)}),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 r=new Ti(this.buttonConfig).mapVariant(t,a.metadata,s?.pitchByBeat);i("buttons",1,"Button mapping complete"),E?.throwIfAborted(),i("conversion",0,"Converting to playable chart...");const c=this.convertToChart(r,B);i("conversion",1,"Chart conversion complete"),E?.throwIfAborted(),i("finalizing",0,"Finalizing level...");const G=this.buildLevel(c,r,a,s,"custom");return i("finalizing",1,"Level generation complete"),G}async generateAtDensities(A,B,I,Q,E){const i=new Map;E?.throwIfAborted();const e=B.audioId;Q?.({stage:"rhythm",progress:0,message:"Starting rhythm generation..."});let a=null;if(this.options.cachedRhythm)a=this.options.cachedRhythm,Q?.({stage:"rhythm",progress:1,message:"Using pre-generated rhythm from store"});else{const s=this.generateCacheKey(e,"rhythm",this.createConfigFingerprint("rhythm"));a=this.getFromCache(s),a?Q?.({stage:"rhythm",progress:1,message:"Rhythm loaded from cache"}):(a=await this.generateRhythm(A,B,void 0,E,!0),this.setCache(s,a),Q?.({stage:"rhythm",progress:1,message:"Rhythm generation complete"}))}E?.throwIfAborted();let C=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const s=this.generateCacheKey(e,"pitch",this.createConfigFingerprint("pitch"));C=this.getFromCache(s),C?Q?.({stage:"pitch",progress:1,message:"Pitch analysis loaded from cache"}):(Q?.({stage:"pitch",progress:0,message:"Starting pitch analysis..."}),C=await this.analyzePitch(A,a),this.setCache(s,C),Q?.({stage:"pitch",progress:1,message:"Pitch analysis complete"}))}E?.throwIfAborted();const o=this.collectGridDecisions(a.analysis.quantizationResult),t=new vi({seed:this.options.seed});for(let s=0;s<I.length;s++){const{label:n,config:r}=I[s];Q?.({stage:"buttons",progress:s/I.length,message:`Generating ${n} density variant...`}),E?.throwIfAborted();const c=t.generateAtDensity(a.composite,r,B,a.analysis.phraseAnalysis,o),D=new Ti(this.buttonConfig).mapVariant(c,a.metadata,C?.pitchByBeat),h=this.convertToChart(D,B),w=this.buildLevel(h,D,a,C,"custom");i.set(n,w)}return Q?.({stage:"finalizing",progress:1,message:"All density variants generated"}),i}collectGridDecisions(A){const B=new Map,I=[...A.streams.low.gridDecisions,...A.streams.mid.gridDecisions,...A.streams.high.gridDecisions];for(const Q of I){const E=B.get(Q.beatIndex);(!E||Q.confidence>E.confidence)&&B.set(Q.beatIndex,Q)}return B}async generateRhythm(A,B,I,Q,E){return await new kg({...this.options.rhythm,skipDifficultyVariants:E}).generate(A,B,Q,I?(a,C,o)=>{I(a,C,o)}:void 0)}async analyzePitch(A,B,I){I?.(.1,"Linking pitch to beats...");const Q={};this.options.pitchAlgorithm!==void 0&&(Q.pitchAlgorithm=this.options.pitchAlgorithm),this.options.crepeModelUrl!==void 0&&(Q.crepeModelUrl=this.options.crepeModelUrl),this.options.resolveUrl!==void 0&&(Q.resolveUrl=this.options.resolveUrl),this.options.voicingThreshold!==void 0&&(Q.pitchDetector={...Q.pitchDetector,voicingThreshold:this.options.voicingThreshold});const E=new Fd(Q),i=await E.linkWithComposite(B.composite,A);I?.(.4,"Analyzing melody contour...");const a=new uN().analyze(i);I?.(.8,"Deriving variant pitches...");let C;if(!B.difficultyVariants)C=a.pitchByBeat;else{const o=this.options.difficulty==="custom"?"medium":this.options.difficulty;C=E.deriveVariantPitches(B.difficultyVariants[o],a.pitchByBeat)}return{...a,pitchByBeat:C}}mapButtons(A,B){const I=new Ti(this.buttonConfig),Q=this.options.difficulty==="custom"?"medium":this.options.difficulty;return I.map(A,Q,B?.pitchByBeat)}convertToChart(A,B){return Oi.fromMappedResult(A.variant,B,A.buttonMetadata,A.rhythmMetadata,A.keyAssignments,A.mappingSources,A.mappingPatternIds)}buildLevel(A,B,I,Q,E){const i={difficulty:E??this.options.difficulty,controllerMode:this.options.controllerMode,rhythmMetadata:B.rhythmMetadata,buttonMetadata:B.buttonMetadata,pitchMetadata:Q?{melodyRange:Q.melodyContour.range.minNote!=="N/A"?{min:Q.melodyContour.range.minNote,max:Q.melodyContour.range.maxNote}:null,directionStats:Q.directionStats,intervalStats:Q.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:I,pitchAnalysis:Q,metadata:i}}}class aW{static toExportData(A,B={}){const{chart:I,metadata:Q,pitchAnalysis:E}=A,i=this.buildDetectedBeats(I),e=this.buildMergedBeats(I),a=this.buildInterpolatedMetadata(I),C=this.buildSubdivisionData(I),o=this.buildChartExportData(I,Q),t=this.buildGenerationMetadata(Q,E);return{version:1,format:"full-beatmap",audioId:I.audioId,audioTitle:B.includeAudioTitle?B.audioTitle:void 0,exportedAt:Date.now(),duration:I.duration,quarterNoteBpm:I.bpm,quarterNoteConfidence:I.chartMetadata.rhythmMetadata.averageDensity,detectedBeats:i,mergedBeats:e,interpolatedMetadata:a,subdivision:C,chart:o,trackReference:B.trackReference,generationSource:"procedural",generationMetadata:t}}static buildDetectedBeats(A){const B=[],I=new Set(A.detectedBeatIndices);for(let Q=0;Q<A.beats.length;Q++){const E=A.beats[Q];I.has(Q)&&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((I,Q)=>({timestamp:I.timestamp,beatInMeasure:I.beatInMeasure,isDownbeat:I.isDownbeat,measureNumber:I.measureNumber,intensity:I.intensity,confidence:I.confidence,requiredKey:I.requiredKey,source:B.has(Q)?"detected":"interpolated",distanceToAnchor:I.quantizationError}))}static buildInterpolatedMetadata(A){const B=A.detectedBeatIndices.length,I=A.beats.length;return{quarterNoteInterval:A.quarterNoteInterval,quarterNoteBpm:A.bpm,quarterNoteConfidence:.9,detectedBeatCount:B,mergedBeatCount:I}}static buildSubdivisionData(A){const B=A.beats.map((e,a)=>this.chartedBeatToExportBeat(e,a,A.detectedBeatIndices)),I=new Set,Q=[];B.forEach((e,a)=>{I.add(e.subdivisionType),Q.push([a,e.subdivisionType])});const E={beatSubdivisions:Q,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,I){const Q=I.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:Q,originalBeatIndex:Q?B:void 0,subdivisionType:A.subdivisionType,quarterNoteIndex:A.quarterNoteIndex,subdivisionPosition:A.subdivisionPosition,sourceBand:A.sourceBand,quantizationError:A.quantizationError}}static buildChartExportData(A,B){const I=A.beats.map(E=>E.requiredKey).filter(E=>E!==void 0),Q=[...new Set(I)];return Q.length===0?null:{style:B.controllerMode==="ddr"?"ddr":B.controllerMode==="guitar_hero"?"guitar":"tap",keyCount:Q.length,usedKeys:Q}}static buildGenerationMetadata(A,B){const I=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:I.difficulty,bandsAnalyzed:I.bandsAnalyzed,transientsDetected:I.transientsDetected,averageDensity:I.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 I=B.data,Q=this.reconstructChart(I),E=this.reconstructVariant(I,Q),i=this.reconstructRhythm(I,Q),e=this.reconstructPitchAnalysis(I),a=this.reconstructMetadata(I,Q);return{chart:Q,variant:E,rhythm:i,pitchAnalysis:e,metadata:a}}static reconstructChart(A){if(!A.subdivision)return this.reconstructChartFromMergedBeats(A);const B=A.subdivision.beats.map((i,e)=>({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})),I=A.subdivision.beats.map((i,e)=>i.isDetected?e:-1).filter(i=>i>=0),Q=this.reconstructDownbeatConfig(B),E=this.reconstructChartMetadata(A);return{audioId:A.audioId,duration:A.duration,beats:B,detectedBeatIndices:I,downbeatConfig:Q,quarterNoteInterval:A.interpolatedMetadata.quarterNoteInterval,bpm:A.quarterNoteBpm,chartMetadata:E}}static reconstructChartFromMergedBeats(A){const B=A.mergedBeats.map((i,e)=>({timestamp:i.timestamp,beatInMeasure:i.beatInMeasure,isDownbeat:i.isDownbeat,measureNumber:i.measureNumber,intensity:i.intensity,confidence:i.confidence,requiredKey:i.requiredKey,quarterNoteIndex:e,subdivisionPosition:0,isDetected:i.source==="detected",subdivisionType:"quarter",sourceBand:"mid",quantizationError:i.distanceToAnchor})),I=A.mergedBeats.map((i,e)=>i.source==="detected"?e:-1).filter(i=>i>=0),Q=this.reconstructDownbeatConfig(B),E=this.reconstructChartMetadata(A);return{audioId:A.audioId,duration:A.duration,beats:B,detectedBeatIndices:I,downbeatConfig:Q,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 I={beatsPerMeasure:4};return{segments:[{startBeat:0,downbeatBeatIndex:B[0]?.measureNumber??0,timeSignature:I}]}}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(I=>I.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 I=A.generationMetadata,Q=this.parseDifficultyLevel(I?.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:Q,beats:E,isUnedited:!0,editType:"none",editAmount:0,patternsInserted:I?.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 I=A.generationMetadata,Q=this.parseDifficultyLevel(I?.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")},e=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})),C={low:0,mid:0,high:0};for(const t of a)C[t.sourceBand]++;const o={beats:a,sections:[],naturalDifficulty:Q,quarterNoteInterval:A.interpolatedMetadata.quarterNoteInterval,metadata:{totalBeats:a.length,sectionCount:0,beatsPerBand:C,sectionsPerBand:{low:0,mid:0,high:0}}};return{difficultyVariants:{easy:{...e,difficulty:"easy"},medium:{...e,difficulty:"medium"},hard:{...e,difficulty:"hard"},natural:{...e,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:Q,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:Q}},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,Q)}}static buildFullRhythmMetadata(A,B){const I=A.generationMetadata;return{difficulty:this.parseDifficultyPreset(I?.difficulty),bandsAnalyzed:["low","mid","high"],transientsDetected:A.detectedBeats.length,transientsFilteredByIntensity:0,densityValidationRetries:0,phrasesDetected:0,averageDensity:I?.rhythmMetadata?.averageDensity??.5,naturalDifficulty:B,generationConfig:{difficulty:this.parseDifficultyPreset(I?.difficulty),outputMode:"composite",measureStartOffset:0,minimumTransientIntensity:.1,transientConfig:void 0,rhythmicBalanceConfig:{strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},seed:I?.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 I=A.generationMetadata,Q=this.parseDifficultyPreset(I?.difficulty),E=I?.controllerMode??"ddr";return{difficulty:Q,controllerMode:E,rhythmMetadata:this.buildFullRhythmMetadata(A,this.parseDifficultyLevel(I?.difficulty)),buttonMetadata:{controllerMode:E,keysUsed:A.chart?.usedKeys??[],pitchInfluencedBeats:I?.pitchInfluenceWeight&&I.pitchInfluenceWeight>0?B.beats.filter(i=>i.requiredKey).length:0,patternInfluencedBeats:B.beats.filter(i=>i.requiredKey).length-(I?.pitchInfluenceWeight&&I.pitchInfluenceWeight>0?B.beats.filter(i=>i.requiredKey).length:0),patternsUsed:I?.patternsUsed??[],buttonDistribution:new Map},pitchMetadata:I?.directionStats||I?.intervalStats?{melodyRange:null,directionStats:I.directionStats??null,intervalStats:I.intervalStats??null}:null,chartMetadata:{totalBeats:B.beats.length,detectedBeats:B.detectedBeatIndices.length,generatedBeats:B.beats.length-B.detectedBeatIndices.length},generationConfig:{difficulty:Q,controllerMode:E,rhythm:{},buttons:{pitchInfluenceWeight:I?.pitchInfluenceWeight??1},seed:I?.seed}}}static toJSON(A,B={}){const I=this.toExportData(A,B);return JSON.stringify(I,null,2)}static fromJSON(A){let B;try{B=JSON.parse(A)}catch(Q){throw new Error(`Invalid JSON: ${Q instanceof Error?Q.message:"Unknown error"}`)}const I=this.validate(B);if(!I.success||!I.data)throw new Error(`Invalid level data: ${I.error??"Unknown error"}`);return this.fromExportData(I.data)}static async saveToFile(A,B,I={}){const Q=await Promise.resolve().then(()=>Eg),E=this.toJSON(A,I);await Q.writeFile(B,E,"utf-8")}static async loadFromFile(A){const I=await(await Promise.resolve().then(()=>Eg)).readFile(A,"utf-8");return this.fromJSON(I)}static validate(A){const B=[];if(typeof A!="object"||A===null)return{success:!1,error:"Data must be a non-null object"};const I=A;if(I.version!==1)return{success:!1,error:`Unsupported version: ${I.version}. Expected 1.`};if(I.format!=="full-beatmap")return{success:!1,error:`Invalid format: ${I.format}. Expected 'full-beatmap'.`};const Q=["audioId","duration","quarterNoteBpm","detectedBeats","mergedBeats"];for(const E of Q)if(!(E in I))return{success:!1,error:`Missing required field: ${E}`};if(!Array.isArray(I.detectedBeats))return{success:!1,error:"detectedBeats must be an array"};if(!Array.isArray(I.mergedBeats))return{success:!1,error:"mergedBeats must be an array"};if(!I.subdivision||typeof I.subdivision!="object")B.push("No subdivision data - level may not be playable");else{const E=I.subdivision;if(!Array.isArray(E.beats))return{success:!1,error:"subdivision.beats must be an array"}}if(I.chart===null)B.push("No chart data - level has no key assignments");else if(I.chart!==void 0&&typeof I.chart!="object")return{success:!1,error:"chart must be an object or null"};return typeof I.interpolatedMetadata!="object"||I.interpolatedMetadata===null?{success:!1,error:"interpolatedMetadata must be an object"}:th(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 I={};for(const[Q,E]of Object.entries(A))if(E){const i={includeAudioTitle:B.includeAudioTitle,audioTitle:B.audioTitle};I[Q]=this.toExportData(E,i)}return{version:1,format:"level-pack",exportedAt:Date.now(),trackReference:B.trackReference,difficulties:I}}static fromPack(A){const B={};for(const[I,Q]of Object.entries(A.difficulties))if(Q)try{B[I]=this.fromExportData(Q)}catch{}return B}static packToJSON(A,B={}){const I=this.toPack(A,B);return JSON.stringify(I,null,2)}static packFromJSON(A){let B;try{B=JSON.parse(A)}catch(I){throw new Error(`Invalid JSON: ${I instanceof Error?I.message:"Unknown error"}`)}if(!sh(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(`
|