From e6644025285dd3614054f4d54864abb5421dc6ae Mon Sep 17 00:00:00 2001 From: legop3 Date: Fri, 26 Jun 2026 00:55:29 -0400 Subject: [PATCH] midi awawa slopcoding --- server/public/assets/index-BA_CXART.js | 137 ++++ server/public/assets/index-CfAeG6CY.js | 137 ---- ...{index-CdgtactY.css => index-DL3_eVjU.css} | 2 +- server/public/index.html | 4 +- webui/package-lock.json | 7 + webui/package.json | 1 + webui/src/components/VipPanel/index.jsx | 4 +- .../vip/VipMidiBeeperCard/StatusRow.jsx | 13 + .../vip/VipMidiBeeperCard/constants.js | 39 ++ .../vip/VipMidiBeeperCard/index.jsx | 647 ++++++++++++++++++ .../vip/VipMidiBeeperCard/midiBeeperUtils.js | 436 ++++++++++++ 11 files changed, 1286 insertions(+), 141 deletions(-) create mode 100644 server/public/assets/index-BA_CXART.js delete mode 100644 server/public/assets/index-CfAeG6CY.js rename server/public/assets/{index-CdgtactY.css => index-DL3_eVjU.css} (70%) create mode 100644 webui/src/components/vip/VipMidiBeeperCard/StatusRow.jsx create mode 100644 webui/src/components/vip/VipMidiBeeperCard/constants.js create mode 100644 webui/src/components/vip/VipMidiBeeperCard/index.jsx create mode 100644 webui/src/components/vip/VipMidiBeeperCard/midiBeeperUtils.js diff --git a/server/public/assets/index-BA_CXART.js b/server/public/assets/index-BA_CXART.js new file mode 100644 index 00000000..5b586c77 --- /dev/null +++ b/server/public/assets/index-BA_CXART.js @@ -0,0 +1,137 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OrbitControls-BJ-UXxdt.js","assets/three.module--MGUDD-H.js"])))=>i.map(i=>d[i]); +(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))i(u);new MutationObserver(u=>{for(const h of u)if(h.type==="childList")for(const m of h.addedNodes)m.tagName==="LINK"&&m.rel==="modulepreload"&&i(m)}).observe(document,{childList:!0,subtree:!0});function l(u){const h={};return u.integrity&&(h.integrity=u.integrity),u.referrerPolicy&&(h.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?h.credentials="include":u.crossOrigin==="anonymous"?h.credentials="omit":h.credentials="same-origin",h}function i(u){if(u.ep)return;u.ep=!0;const h=l(u);fetch(u.href,h)}})();function em(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var N9={exports:{}},b8={};var Li;function cm(){if(Li)return b8;Li=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function l(i,u,h){var m=null;if(h!==void 0&&(m=""+h),u.key!==void 0&&(m=""+u.key),"key"in u){h={};for(var p in u)p!=="key"&&(h[p]=u[p])}else h=u;return u=h.ref,{$$typeof:t,type:i,key:m,ref:u!==void 0?u:null,props:h}}return b8.Fragment=a,b8.jsx=l,b8.jsxs=l,b8}var Bi;function am(){return Bi||(Bi=1,N9.exports=cm()),N9.exports}var r=am(),j9={exports:{}},D1={};var Ni;function nm(){if(Ni)return D1;Ni=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.portal"),l=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),h=Symbol.for("react.consumer"),m=Symbol.for("react.context"),p=Symbol.for("react.forward_ref"),x=Symbol.for("react.suspense"),z=Symbol.for("react.memo"),g=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),y=Symbol.iterator;function w(E){return E===null||typeof E!="object"?null:(E=y&&E[y]||E["@@iterator"],typeof E=="function"?E:null)}var H={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},S=Object.assign,C={};function L(E,_,K){this.props=E,this.context=_,this.refs=C,this.updater=K||H}L.prototype.isReactComponent={},L.prototype.setState=function(E,_){if(typeof E!="object"&&typeof E!="function"&&E!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,E,_,"setState")},L.prototype.forceUpdate=function(E){this.updater.enqueueForceUpdate(this,E,"forceUpdate")};function V(){}V.prototype=L.prototype;function A(E,_,K){this.props=E,this.context=_,this.refs=C,this.updater=K||H}var F=A.prototype=new V;F.constructor=A,S(F,L.prototype),F.isPureReactComponent=!0;var T=Array.isArray;function R(){}var B={H:null,A:null,T:null,S:null},j=Object.prototype.hasOwnProperty;function U(E,_,K){var a1=K.ref;return{$$typeof:t,type:E,key:_,ref:a1!==void 0?a1:null,props:K}}function O(E,_){return U(E.type,_,E.props)}function q(E){return typeof E=="object"&&E!==null&&E.$$typeof===t}function Z(E){var _={"=":"=0",":":"=2"};return"$"+E.replace(/[=:]/g,function(K){return _[K]})}var e1=/\/+/g;function l1(E,_){return typeof E=="object"&&E!==null&&E.key!=null?Z(""+E.key):_.toString(36)}function J(E){switch(E.status){case"fulfilled":return E.value;case"rejected":throw E.reason;default:switch(typeof E.status=="string"?E.then(R,R):(E.status="pending",E.then(function(_){E.status==="pending"&&(E.status="fulfilled",E.value=_)},function(_){E.status==="pending"&&(E.status="rejected",E.reason=_)})),E.status){case"fulfilled":return E.value;case"rejected":throw E.reason}}throw E}function k(E,_,K,a1,p1){var z1=typeof E;(z1==="undefined"||z1==="boolean")&&(E=null);var V1=!1;if(E===null)V1=!0;else switch(z1){case"bigint":case"string":case"number":V1=!0;break;case"object":switch(E.$$typeof){case t:case a:V1=!0;break;case g:return V1=E._init,k(V1(E._payload),_,K,a1,p1)}}if(V1)return p1=p1(E),V1=a1===""?"."+l1(E,0):a1,T(p1)?(K="",V1!=null&&(K=V1.replace(e1,"$&/")+"/"),k(p1,_,K,"",function(Z1){return Z1})):p1!=null&&(q(p1)&&(p1=O(p1,K+(p1.key==null||E&&E.key===p1.key?"":(""+p1.key).replace(e1,"$&/")+"/")+V1)),_.push(p1)),1;V1=0;var A1=a1===""?".":a1+":";if(T(E))for(var N1=0;N1>>1,m1=k[v1];if(0>>1;v1u(K,W))a1u(p1,K)?(k[v1]=p1,k[a1]=W,v1=a1):(k[v1]=K,k[_]=W,v1=_);else if(a1u(p1,W))k[v1]=p1,k[a1]=W,v1=a1;else break t}}return $}function u(k,$){var W=k.sortIndex-$.sortIndex;return W!==0?W:k.id-$.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var h=performance;t.unstable_now=function(){return h.now()}}else{var m=Date,p=m.now();t.unstable_now=function(){return m.now()-p}}var x=[],z=[],g=1,b=null,y=3,w=!1,H=!1,S=!1,C=!1,L=typeof setTimeout=="function"?setTimeout:null,V=typeof clearTimeout=="function"?clearTimeout:null,A=typeof setImmediate<"u"?setImmediate:null;function F(k){for(var $=l(z);$!==null;){if($.callback===null)i(z);else if($.startTime<=k)i(z),$.sortIndex=$.expirationTime,a(x,$);else break;$=l(z)}}function T(k){if(S=!1,F(k),!H)if(l(x)!==null)H=!0,R||(R=!0,Z());else{var $=l(z);$!==null&&J(T,$.startTime-k)}}var R=!1,B=-1,j=5,U=-1;function O(){return C?!0:!(t.unstable_now()-Uk&&O());){var v1=b.callback;if(typeof v1=="function"){b.callback=null,y=b.priorityLevel;var m1=v1(b.expirationTime<=k);if(k=t.unstable_now(),typeof m1=="function"){b.callback=m1,F(k),$=!0;break e}b===l(x)&&i(x),F(k)}else i(x);b=l(x)}if(b!==null)$=!0;else{var E=l(z);E!==null&&J(T,E.startTime-k),$=!1}}break t}finally{b=null,y=W,w=!1}$=void 0}}finally{$?Z():R=!1}}}var Z;if(typeof A=="function")Z=function(){A(q)};else if(typeof MessageChannel<"u"){var e1=new MessageChannel,l1=e1.port2;e1.port1.onmessage=q,Z=function(){l1.postMessage(null)}}else Z=function(){L(q,0)};function J(k,$){B=L(function(){k(t.unstable_now())},$)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(k){k.callback=null},t.unstable_forceFrameRate=function(k){0>k||125v1?(k.sortIndex=W,a(z,k),l(x)===null&&k===l(z)&&(S?(V(B),B=-1):S=!0,J(T,W-v1))):(k.sortIndex=m1,a(x,k),H||w||(H=!0,R||(R=!0,Z()))),k},t.unstable_shouldYield=O,t.unstable_wrapCallback=function(k){var $=y;return function(){var W=y;y=$;try{return k.apply(this,arguments)}finally{y=W}}}})(R9)),R9}var ki;function rm(){return ki||(ki=1,k9.exports=lm()),k9.exports}var E9={exports:{}},G2={};var Ri;function im(){if(Ri)return G2;Ri=1;var t=Ic();function a(x){var z="https://react.dev/errors/"+x;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(a){console.error(a)}}return t(),E9.exports=im(),E9.exports}var Ti;function sm(){if(Ti)return M8;Ti=1;var t=rm(),a=Ic(),l=Co();function i(e){var c="https://react.dev/errors/"+e;if(1m1||(e.current=v1[m1],v1[m1]=null,m1--)}function K(e,c){m1++,v1[m1]=e.current,e.current=c}var a1=E(null),p1=E(null),z1=E(null),V1=E(null);function A1(e,c){switch(K(z1,c),K(p1,e),K(a1,null),c.nodeType){case 9:case 11:e=(e=c.documentElement)&&(e=e.namespaceURI)?Jr(e):0;break;default:if(e=c.tagName,c=c.namespaceURI)c=Jr(c),e=Wr(c,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}_(a1),K(a1,e)}function N1(){_(a1),_(p1),_(z1)}function Z1(e){e.memoizedState!==null&&K(V1,e);var c=a1.current,n=Wr(c,e.type);c!==n&&(K(p1,e),K(a1,n))}function Y1(e){p1.current===e&&(_(a1),_(p1)),V1.current===e&&(_(V1),p8._currentValue=W)}var E1,l2;function i1(e){if(E1===void 0)try{throw Error()}catch(n){var c=n.stack.trim().match(/\n( *(at )?)/);E1=c&&c[1]||"",l2=-1)":-1d||D[o]!==Q[d]){var n1=` +`+D[o].replace(" at new "," at ");return e.displayName&&n1.includes("")&&(n1=n1.replace("",e.displayName)),n1}while(1<=o&&0<=d);break}}}finally{S1=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:"")?i1(n):""}function b1(e,c){switch(e.tag){case 26:case 27:case 5:return i1(e.type);case 16:return i1("Lazy");case 13:return e.child!==c&&c!==null?i1("Suspense Fallback"):i1("Suspense");case 19:return i1("SuspenseList");case 0:case 15:return g1(e.type,!1);case 11:return g1(e.type.render,!1);case 1:return g1(e.type,!0);case 31:return i1("Activity");default:return""}}function j1(e){try{var c="",n=null;do c+=b1(e,n),n=e,e=e.return;while(e);return c}catch(o){return` +Error generating stack: `+o.message+` +`+o.stack}}var k1=Object.prototype.hasOwnProperty,d1=t.unstable_scheduleCallback,w1=t.unstable_cancelCallback,T1=t.unstable_shouldYield,u1=t.unstable_requestPaint,x1=t.unstable_now,q1=t.unstable_getCurrentPriorityLevel,L1=t.unstable_ImmediatePriority,_1=t.unstable_UserBlockingPriority,s1=t.unstable_NormalPriority,G=t.unstable_LowPriority,c1=t.unstable_IdlePriority,M1=t.log,s2=t.unstable_setDisableYieldValue,o2=null,M2=null;function n4(e){if(typeof M1=="function"&&s2(e),M2&&typeof M2.setStrictMode=="function")try{M2.setStrictMode(o2,e)}catch{}}var y1=Math.clz32?Math.clz32:G1,f2=Math.log,a2=Math.LN2;function G1(e){return e>>>=0,e===0?32:31-(f2(e)/a2|0)|0}var t2=256,P2=262144,_4=4194304;function m4(e){var c=e&42;if(c!==0)return c;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function y2(e,c,n){var o=e.pendingLanes;if(o===0)return 0;var d=0,v=e.suspendedLanes,M=e.pingedLanes;e=e.warmLanes;var N=o&134217727;return N!==0?(o=N&~v,o!==0?d=m4(o):(M&=N,M!==0?d=m4(M):n||(n=N&~e,n!==0&&(d=m4(n))))):(N=o&~v,N!==0?d=m4(N):M!==0?d=m4(M):n||(n=o&~e,n!==0&&(d=m4(n)))),d===0?0:c!==0&&c!==d&&(c&v)===0&&(v=d&-d,n=c&-c,v>=n||v===32&&(n&4194048)!==0)?c:d}function B4(e,c){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&c)===0}function Oh(e,c){switch(e){case 1:case 2:case 4:case 8:case 64:return c+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return c+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ja(){var e=_4;return _4<<=1,(_4&62914560)===0&&(_4=4194304),e}function ze(e){for(var c=[],n=0;31>n;n++)c.push(e);return c}function B0(e,c){e.pendingLanes|=c,c!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Uh(e,c,n,o,d,v){var M=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var N=e.entanglements,D=e.expirationTimes,Q=e.hiddenUpdates;for(n=M&~n;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Yh=/[\n"\\]/g;function p4(e){return e.replace(Yh,function(c){return"\\"+c.charCodeAt(0).toString(16)+" "})}function Se(e,c,n,o,d,v,M,N){e.name="",M!=null&&typeof M!="function"&&typeof M!="symbol"&&typeof M!="boolean"?e.type=M:e.removeAttribute("type"),c!=null?M==="number"?(c===0&&e.value===""||e.value!=c)&&(e.value=""+v4(c)):e.value!==""+v4(c)&&(e.value=""+v4(c)):M!=="submit"&&M!=="reset"||e.removeAttribute("value"),c!=null?He(e,M,v4(c)):n!=null?He(e,M,v4(n)):o!=null&&e.removeAttribute("value"),d==null&&v!=null&&(e.defaultChecked=!!v),d!=null&&(e.checked=d&&typeof d!="function"&&typeof d!="symbol"),N!=null&&typeof N!="function"&&typeof N!="symbol"&&typeof N!="boolean"?e.name=""+v4(N):e.removeAttribute("name")}function Za(e,c,n,o,d,v,M,N){if(v!=null&&typeof v!="function"&&typeof v!="symbol"&&typeof v!="boolean"&&(e.type=v),c!=null||n!=null){if(!(v!=="submit"&&v!=="reset"||c!=null)){Ce(e);return}n=n!=null?""+v4(n):"",c=c!=null?""+v4(c):n,N||c===e.value||(e.value=c),e.defaultValue=c}o=o??d,o=typeof o!="function"&&typeof o!="symbol"&&!!o,e.checked=N?e.checked:!!o,e.defaultChecked=!!o,M!=null&&typeof M!="function"&&typeof M!="symbol"&&typeof M!="boolean"&&(e.name=M),Ce(e)}function He(e,c,n){c==="number"&&t5(e.ownerDocument)===e||e.defaultValue===""+n||(e.defaultValue=""+n)}function V6(e,c,n,o){if(e=e.options,c){c={};for(var d=0;d"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Ne=!1;if(Q4)try{var k0={};Object.defineProperty(k0,"passive",{get:function(){Ne=!0}}),window.addEventListener("test",k0,k0),window.removeEventListener("test",k0,k0)}catch{Ne=!1}var y3=null,je=null,c5=null;function Ja(){if(c5)return c5;var e,c=je,n=c.length,o,d="value"in y3?y3.value:y3.textContent,v=d.length;for(e=0;e=T0),nn=" ",ln=!1;function rn(e,c){switch(e){case"keyup":return yd.indexOf(c.keyCode)!==-1;case"keydown":return c.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function sn(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var j6=!1;function Cd(e,c){switch(e){case"compositionend":return sn(c);case"keypress":return c.which!==32?null:(ln=!0,nn);case"textInput":return e=c.data,e===nn&&ln?null:e;default:return null}}function Sd(e,c){if(j6)return e==="compositionend"||!Te&&rn(e,c)?(e=Ja(),c5=je=y3=null,j6=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(c.ctrlKey||c.altKey||c.metaKey)||c.ctrlKey&&c.altKey){if(c.char&&1=c)return{node:n,offset:c-e};e=o}t:{for(;n;){if(n.nextSibling){n=n.nextSibling;break t}n=n.parentNode}n=void 0}n=pn(n)}}function xn(e,c){return e&&c?e===c?!0:e&&e.nodeType===3?!1:c&&c.nodeType===3?xn(e,c.parentNode):"contains"in e?e.contains(c):e.compareDocumentPosition?!!(e.compareDocumentPosition(c)&16):!1:!1}function zn(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var c=t5(e.document);c instanceof e.HTMLIFrameElement;){try{var n=typeof c.contentWindow.location.href=="string"}catch{n=!1}if(n)e=c.contentWindow;else break;c=t5(e.document)}return c}function De(e){var c=e&&e.nodeName&&e.nodeName.toLowerCase();return c&&(c==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||c==="textarea"||e.contentEditable==="true")}var Fd=Q4&&"documentMode"in document&&11>=document.documentMode,F6=null,Oe=null,O0=null,Ue=!1;function bn(e,c,n){var o=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Ue||F6==null||F6!==t5(o)||(o=F6,"selectionStart"in o&&De(o)?o={start:o.selectionStart,end:o.selectionEnd}:(o=(o.ownerDocument&&o.ownerDocument.defaultView||window).getSelection(),o={anchorNode:o.anchorNode,anchorOffset:o.anchorOffset,focusNode:o.focusNode,focusOffset:o.focusOffset}),O0&&D0(O0,o)||(O0=o,o=K5(Oe,"onSelect"),0>=M,d-=M,D4=1<<32-y1(c)+d|n<$1?(J1=H1,H1=null):J1=H1.sibling;var c2=X(P,H1,Y[$1],r1);if(c2===null){H1===null&&(H1=J1);break}e&&H1&&c2.alternate===null&&c(P,H1),I=v(c2,I,$1),e2===null?B1=c2:e2.sibling=c2,e2=c2,H1=J1}if($1===Y.length)return n(P,H1),W1&&J4(P,$1),B1;if(H1===null){for(;$1$1?(J1=H1,H1=null):J1=H1.sibling;var $3=X(P,H1,c2.value,r1);if($3===null){H1===null&&(H1=J1);break}e&&H1&&$3.alternate===null&&c(P,H1),I=v($3,I,$1),e2===null?B1=$3:e2.sibling=$3,e2=$3,H1=J1}if(c2.done)return n(P,H1),W1&&J4(P,$1),B1;if(H1===null){for(;!c2.done;$1++,c2=Y.next())c2=o1(P,c2.value,r1),c2!==null&&(I=v(c2,I,$1),e2===null?B1=c2:e2.sibling=c2,e2=c2);return W1&&J4(P,$1),B1}for(H1=o(H1);!c2.done;$1++,c2=Y.next())c2=t1(H1,P,$1,c2.value,r1),c2!==null&&(e&&c2.alternate!==null&&H1.delete(c2.key===null?$1:c2.key),I=v(c2,I,$1),e2===null?B1=c2:e2.sibling=c2,e2=c2);return e&&H1.forEach(function(tm){return c(P,tm)}),W1&&J4(P,$1),B1}function d2(P,I,Y,r1){if(typeof Y=="object"&&Y!==null&&Y.type===S&&Y.key===null&&(Y=Y.props.children),typeof Y=="object"&&Y!==null){switch(Y.$$typeof){case w:t:{for(var B1=Y.key;I!==null;){if(I.key===B1){if(B1=Y.type,B1===S){if(I.tag===7){n(P,I.sibling),r1=d(I,Y.props.children),r1.return=P,P=r1;break t}}else if(I.elementType===B1||typeof B1=="object"&&B1!==null&&B1.$$typeof===j&&n6(B1)===I.type){n(P,I.sibling),r1=d(I,Y.props),G0(r1,Y),r1.return=P,P=r1;break t}n(P,I);break}else c(P,I);I=I.sibling}Y.type===S?(r1=W3(Y.props.children,P.mode,r1,Y.key),r1.return=P,P=r1):(r1=d5(Y.type,Y.key,Y.props,null,P.mode,r1),G0(r1,Y),r1.return=P,P=r1)}return M(P);case H:t:{for(B1=Y.key;I!==null;){if(I.key===B1)if(I.tag===4&&I.stateNode.containerInfo===Y.containerInfo&&I.stateNode.implementation===Y.implementation){n(P,I.sibling),r1=d(I,Y.children||[]),r1.return=P,P=r1;break t}else{n(P,I);break}else c(P,I);I=I.sibling}r1=Ke(Y,P.mode,r1),r1.return=P,P=r1}return M(P);case j:return Y=n6(Y),d2(P,I,Y,r1)}if(J(Y))return C1(P,I,Y,r1);if(Z(Y)){if(B1=Z(Y),typeof B1!="function")throw Error(i(150));return Y=B1.call(Y),R1(P,I,Y,r1)}if(typeof Y.then=="function")return d2(P,I,z5(Y),r1);if(Y.$$typeof===A)return d2(P,I,v5(P,Y),r1);b5(P,Y)}return typeof Y=="string"&&Y!==""||typeof Y=="number"||typeof Y=="bigint"?(Y=""+Y,I!==null&&I.tag===6?(n(P,I.sibling),r1=d(I,Y),r1.return=P,P=r1):(n(P,I),r1=Ye(Y,P.mode,r1),r1.return=P,P=r1),M(P)):n(P,I)}return function(P,I,Y,r1){try{P0=0;var B1=d2(P,I,Y,r1);return $6=null,B1}catch(H1){if(H1===I6||H1===g5)throw H1;var e2=r4(29,H1,null,P.mode);return e2.lanes=r1,e2.return=P,e2}finally{}}}var r6=In(!0),$n=In(!1),A3=!1;function i7(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function s7(e,c){e=e.updateQueue,c.updateQueue===e&&(c.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function V3(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function L3(e,c,n){var o=e.updateQueue;if(o===null)return null;if(o=o.shared,(n2&2)!==0){var d=o.pending;return d===null?c.next=c:(c.next=d.next,d.next=c),o.pending=c,c=h5(e),An(e,null,n),c}return u5(e,o,c,n),h5(e)}function Y0(e,c,n){if(c=c.updateQueue,c!==null&&(c=c.shared,(n&4194048)!==0)){var o=c.lanes;o&=e.pendingLanes,n|=o,c.lanes=n,ka(e,n)}}function o7(e,c){var n=e.updateQueue,o=e.alternate;if(o!==null&&(o=o.updateQueue,n===o)){var d=null,v=null;if(n=n.firstBaseUpdate,n!==null){do{var M={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};v===null?d=v=M:v=v.next=M,n=n.next}while(n!==null);v===null?d=v=c:v=v.next=c}else d=v=c;n={baseState:o.baseState,firstBaseUpdate:d,lastBaseUpdate:v,shared:o.shared,callbacks:o.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=c:e.next=c,n.lastBaseUpdate=c}var u7=!1;function K0(){if(u7){var e=U6;if(e!==null)throw e}}function Q0(e,c,n,o){u7=!1;var d=e.updateQueue;A3=!1;var v=d.firstBaseUpdate,M=d.lastBaseUpdate,N=d.shared.pending;if(N!==null){d.shared.pending=null;var D=N,Q=D.next;D.next=null,M===null?v=Q:M.next=Q,M=D;var n1=e.alternate;n1!==null&&(n1=n1.updateQueue,N=n1.lastBaseUpdate,N!==M&&(N===null?n1.firstBaseUpdate=Q:N.next=Q,n1.lastBaseUpdate=D))}if(v!==null){var o1=d.baseState;M=0,n1=Q=D=null,N=v;do{var X=N.lane&-536870913,t1=X!==N.lane;if(t1?(X1&X)===X:(o&X)===X){X!==0&&X===O6&&(u7=!0),n1!==null&&(n1=n1.next={lane:0,tag:N.tag,payload:N.payload,callback:null,next:null});t:{var C1=e,R1=N;X=c;var d2=n;switch(R1.tag){case 1:if(C1=R1.payload,typeof C1=="function"){o1=C1.call(d2,o1,X);break t}o1=C1;break t;case 3:C1.flags=C1.flags&-65537|128;case 0:if(C1=R1.payload,X=typeof C1=="function"?C1.call(d2,o1,X):C1,X==null)break t;o1=b({},o1,X);break t;case 2:A3=!0}}X=N.callback,X!==null&&(e.flags|=64,t1&&(e.flags|=8192),t1=d.callbacks,t1===null?d.callbacks=[X]:t1.push(X))}else t1={lane:X,tag:N.tag,payload:N.payload,callback:N.callback,next:null},n1===null?(Q=n1=t1,D=o1):n1=n1.next=t1,M|=X;if(N=N.next,N===null){if(N=d.shared.pending,N===null)break;t1=N,N=t1.next,t1.next=null,d.lastBaseUpdate=t1,d.shared.pending=null}}while(!0);n1===null&&(D=o1),d.baseState=D,d.firstBaseUpdate=Q,d.lastBaseUpdate=n1,v===null&&(d.shared.lanes=0),k3|=M,e.lanes=M,e.memoizedState=o1}}function Zn(e,c){if(typeof e!="function")throw Error(i(191,e));e.call(c)}function Pn(e,c){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ev?v:8;var M=k.T,N={};k.T=N,L7(e,!1,c,n);try{var D=d(),Q=k.S;if(Q!==null&&Q(N,D),D!==null&&typeof D=="object"&&typeof D.then=="function"){var n1=Ud(D,o);W0(e,c,n1,h4(e))}else W0(e,c,o,h4(e))}catch(o1){W0(e,c,{then:function(){},status:"rejected",reason:o1},h4())}finally{$.p=v,M!==null&&N.types!==null&&(M.types=N.types),k.T=M}}function Yd(){}function A7(e,c,n,o){if(e.tag!==5)throw Error(i(476));var d=Cl(e).queue;wl(e,d,c,W,n===null?Yd:function(){return Sl(e),n(o)})}function Cl(e){var c=e.memoizedState;if(c!==null)return c;c={memoizedState:W,baseState:W,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:c3,lastRenderedState:W},next:null};var n={};return c.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:c3,lastRenderedState:n},next:null},e.memoizedState=c,e=e.alternate,e!==null&&(e.memoizedState=c),c}function Sl(e){var c=Cl(e);c.next===null&&(c=e.alternate.memoizedState),W0(e,c.next.queue,{},h4())}function V7(){return I2(p8)}function Hl(){return V2().memoizedState}function Al(){return V2().memoizedState}function Kd(e){for(var c=e.return;c!==null;){switch(c.tag){case 24:case 3:var n=h4();e=V3(n);var o=L3(c,e,n);o!==null&&(a4(o,c,n),Y0(o,c,n)),c={cache:a7()},e.payload=c;return}c=c.return}}function Qd(e,c,n){var o=h4();n={lane:o,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},B5(e)?Ll(c,n):(n=Pe(e,c,n,o),n!==null&&(a4(n,e,o),Bl(n,c,o)))}function Vl(e,c,n){var o=h4();W0(e,c,n,o)}function W0(e,c,n,o){var d={lane:o,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(B5(e))Ll(c,d);else{var v=e.alternate;if(e.lanes===0&&(v===null||v.lanes===0)&&(v=c.lastRenderedReducer,v!==null))try{var M=c.lastRenderedState,N=v(M,n);if(d.hasEagerState=!0,d.eagerState=N,l4(N,M))return u5(e,c,d,0),m2===null&&o5(),!1}catch{}finally{}if(n=Pe(e,c,d,o),n!==null)return a4(n,e,o),Bl(n,c,o),!0}return!1}function L7(e,c,n,o){if(o={lane:2,revertLane:i9(),gesture:null,action:o,hasEagerState:!1,eagerState:null,next:null},B5(e)){if(c)throw Error(i(479))}else c=Pe(e,n,o,2),c!==null&&a4(c,e,2)}function B5(e){var c=e.alternate;return e===I1||c!==null&&c===I1}function Ll(e,c){P6=w5=!0;var n=e.pending;n===null?c.next=c:(c.next=n.next,n.next=c),e.pending=c}function Bl(e,c,n){if((n&4194048)!==0){var o=c.lanes;o&=e.pendingLanes,n|=o,c.lanes=n,ka(e,n)}}var t8={readContext:I2,use:H5,useCallback:w2,useContext:w2,useEffect:w2,useImperativeHandle:w2,useLayoutEffect:w2,useInsertionEffect:w2,useMemo:w2,useReducer:w2,useRef:w2,useState:w2,useDebugValue:w2,useDeferredValue:w2,useTransition:w2,useSyncExternalStore:w2,useId:w2,useHostTransitionStatus:w2,useFormState:w2,useActionState:w2,useOptimistic:w2,useMemoCache:w2,useCacheRefresh:w2};t8.useEffectEvent=w2;var Nl={readContext:I2,use:H5,useCallback:function(e,c){return Y2().memoizedState=[e,c===void 0?null:c],e},useContext:I2,useEffect:ml,useImperativeHandle:function(e,c,n){n=n!=null?n.concat([e]):null,V5(4194308,4,xl.bind(null,c,e),n)},useLayoutEffect:function(e,c){return V5(4194308,4,e,c)},useInsertionEffect:function(e,c){V5(4,2,e,c)},useMemo:function(e,c){var n=Y2();c=c===void 0?null:c;var o=e();if(i6){n4(!0);try{e()}finally{n4(!1)}}return n.memoizedState=[o,c],o},useReducer:function(e,c,n){var o=Y2();if(n!==void 0){var d=n(c);if(i6){n4(!0);try{n(c)}finally{n4(!1)}}}else d=c;return o.memoizedState=o.baseState=d,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:d},o.queue=e,e=e.dispatch=Qd.bind(null,I1,e),[o.memoizedState,e]},useRef:function(e){var c=Y2();return e={current:e},c.memoizedState=e},useState:function(e){e=y7(e);var c=e.queue,n=Vl.bind(null,I1,c);return c.dispatch=n,[e.memoizedState,n]},useDebugValue:S7,useDeferredValue:function(e,c){var n=Y2();return H7(n,e,c)},useTransition:function(){var e=y7(!1);return e=wl.bind(null,I1,e.queue,!0,!1),Y2().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,c,n){var o=I1,d=Y2();if(W1){if(n===void 0)throw Error(i(407));n=n()}else{if(n=c(),m2===null)throw Error(i(349));(X1&127)!==0||Jn(o,c,n)}d.memoizedState=n;var v={value:n,getSnapshot:c};return d.queue=v,ml(tl.bind(null,o,v,e),[e]),o.flags|=2048,Y6(9,{destroy:void 0},Wn.bind(null,o,v,n,c),null),n},useId:function(){var e=Y2(),c=m2.identifierPrefix;if(W1){var n=O4,o=D4;n=(o&~(1<<32-y1(o)-1)).toString(32)+n,c="_"+c+"R_"+n,n=C5++,0<\/script>",v=v.removeChild(v.firstChild);break;case"select":v=typeof o.is=="string"?M.createElement("select",{is:o.is}):M.createElement("select"),o.multiple?v.multiple=!0:o.size&&(v.size=o.size);break;default:v=typeof o.is=="string"?M.createElement(d,{is:o.is}):M.createElement(d)}}v[O2]=c,v[X2]=o;t:for(M=c.child;M!==null;){if(M.tag===5||M.tag===6)v.appendChild(M.stateNode);else if(M.tag!==4&&M.tag!==27&&M.child!==null){M.child.return=M,M=M.child;continue}if(M===c)break t;for(;M.sibling===null;){if(M.return===null||M.return===c)break t;M=M.return}M.sibling.return=M.return,M=M.sibling}c.stateNode=v;t:switch(Z2(v,d,o),d){case"button":case"input":case"select":case"textarea":o=!!o.autoFocus;break t;case"img":o=!0;break t;default:o=!1}o&&n3(c)}}return p2(c),I7(c,c.type,e===null?null:e.memoizedProps,c.pendingProps,n),null;case 6:if(e&&c.stateNode!=null)e.memoizedProps!==o&&n3(c);else{if(typeof o!="string"&&c.stateNode===null)throw Error(i(166));if(e=z1.current,_6(c)){if(e=c.stateNode,n=c.memoizedProps,o=null,d=U2,d!==null)switch(d.tag){case 27:case 5:o=d.memoizedProps}e[O2]=c,e=!!(e.nodeValue===n||o!==null&&o.suppressHydrationWarning===!0||Qr(e.nodeValue,n)),e||S3(c,!0)}else e=Q5(e).createTextNode(o),e[O2]=c,c.stateNode=e}return p2(c),null;case 31:if(n=c.memoizedState,e===null||e.memoizedState!==null){if(o=_6(c),n!==null){if(e===null){if(!o)throw Error(i(318));if(e=c.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(i(557));e[O2]=c}else t6(),(c.flags&128)===0&&(c.memoizedState=null),c.flags|=4;p2(c),e=!1}else n=We(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return c.flags&256?(s4(c),c):(s4(c),null);if((c.flags&128)!==0)throw Error(i(558))}return p2(c),null;case 13:if(o=c.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(d=_6(c),o!==null&&o.dehydrated!==null){if(e===null){if(!d)throw Error(i(318));if(d=c.memoizedState,d=d!==null?d.dehydrated:null,!d)throw Error(i(317));d[O2]=c}else t6(),(c.flags&128)===0&&(c.memoizedState=null),c.flags|=4;p2(c),d=!1}else d=We(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=d),d=!0;if(!d)return c.flags&256?(s4(c),c):(s4(c),null)}return s4(c),(c.flags&128)!==0?(c.lanes=n,c):(n=o!==null,e=e!==null&&e.memoizedState!==null,n&&(o=c.child,d=null,o.alternate!==null&&o.alternate.memoizedState!==null&&o.alternate.memoizedState.cachePool!==null&&(d=o.alternate.memoizedState.cachePool.pool),v=null,o.memoizedState!==null&&o.memoizedState.cachePool!==null&&(v=o.memoizedState.cachePool.pool),v!==d&&(o.flags|=2048)),n!==e&&n&&(c.child.flags|=8192),R5(c,c.updateQueue),p2(c),null);case 4:return N1(),e===null&&h9(c.stateNode.containerInfo),p2(c),null;case 10:return t3(c.type),p2(c),null;case 19:if(_(A2),o=c.memoizedState,o===null)return p2(c),null;if(d=(c.flags&128)!==0,v=o.rendering,v===null)if(d)c8(o,!1);else{if(C2!==0||e!==null&&(e.flags&128)!==0)for(e=c.child;e!==null;){if(v=y5(e),v!==null){for(c.flags|=128,c8(o,!1),e=v.updateQueue,c.updateQueue=e,R5(c,e),c.subtreeFlags=0,e=n,n=c.child;n!==null;)Vn(n,e),n=n.sibling;return K(A2,A2.current&1|2),W1&&J4(c,o.treeForkCount),c.child}e=e.sibling}o.tail!==null&&x1()>D5&&(c.flags|=128,d=!0,c8(o,!1),c.lanes=4194304)}else{if(!d)if(e=y5(v),e!==null){if(c.flags|=128,d=!0,e=e.updateQueue,c.updateQueue=e,R5(c,e),c8(o,!0),o.tail===null&&o.tailMode==="hidden"&&!v.alternate&&!W1)return p2(c),null}else 2*x1()-o.renderingStartTime>D5&&n!==536870912&&(c.flags|=128,d=!0,c8(o,!1),c.lanes=4194304);o.isBackwards?(v.sibling=c.child,c.child=v):(e=o.last,e!==null?e.sibling=v:c.child=v,o.last=v)}return o.tail!==null?(e=o.tail,o.rendering=e,o.tail=e.sibling,o.renderingStartTime=x1(),e.sibling=null,n=A2.current,K(A2,d?n&1|2:n&1),W1&&J4(c,o.treeForkCount),e):(p2(c),null);case 22:case 23:return s4(c),d7(),o=c.memoizedState!==null,e!==null?e.memoizedState!==null!==o&&(c.flags|=8192):o&&(c.flags|=8192),o?(n&536870912)!==0&&(c.flags&128)===0&&(p2(c),c.subtreeFlags&6&&(c.flags|=8192)):p2(c),n=c.updateQueue,n!==null&&R5(c,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),o=null,c.memoizedState!==null&&c.memoizedState.cachePool!==null&&(o=c.memoizedState.cachePool.pool),o!==n&&(c.flags|=2048),e!==null&&_(a6),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),c.memoizedState.cache!==n&&(c.flags|=2048),t3(B2),p2(c),null;case 25:return null;case 30:return null}throw Error(i(156,c.tag))}function ef(e,c){switch(Xe(c),c.tag){case 1:return e=c.flags,e&65536?(c.flags=e&-65537|128,c):null;case 3:return t3(B2),N1(),e=c.flags,(e&65536)!==0&&(e&128)===0?(c.flags=e&-65537|128,c):null;case 26:case 27:case 5:return Y1(c),null;case 31:if(c.memoizedState!==null){if(s4(c),c.alternate===null)throw Error(i(340));t6()}return e=c.flags,e&65536?(c.flags=e&-65537|128,c):null;case 13:if(s4(c),e=c.memoizedState,e!==null&&e.dehydrated!==null){if(c.alternate===null)throw Error(i(340));t6()}return e=c.flags,e&65536?(c.flags=e&-65537|128,c):null;case 19:return _(A2),null;case 4:return N1(),null;case 10:return t3(c.type),null;case 22:case 23:return s4(c),d7(),e!==null&&_(a6),e=c.flags,e&65536?(c.flags=e&-65537|128,c):null;case 24:return t3(B2),null;case 25:return null;default:return null}}function er(e,c){switch(Xe(c),c.tag){case 3:t3(B2),N1();break;case 26:case 27:case 5:Y1(c);break;case 4:N1();break;case 31:c.memoizedState!==null&&s4(c);break;case 13:s4(c);break;case 19:_(A2);break;case 10:t3(c.type);break;case 22:case 23:s4(c),d7(),e!==null&&_(a6);break;case 24:t3(B2)}}function a8(e,c){try{var n=c.updateQueue,o=n!==null?n.lastEffect:null;if(o!==null){var d=o.next;n=d;do{if((n.tag&e)===e){o=void 0;var v=n.create,M=n.inst;o=v(),M.destroy=o}n=n.next}while(n!==d)}}catch(N){i2(c,c.return,N)}}function j3(e,c,n){try{var o=c.updateQueue,d=o!==null?o.lastEffect:null;if(d!==null){var v=d.next;o=v;do{if((o.tag&e)===e){var M=o.inst,N=M.destroy;if(N!==void 0){M.destroy=void 0,d=c;var D=n,Q=N;try{Q()}catch(n1){i2(d,D,n1)}}}o=o.next}while(o!==v)}}catch(n1){i2(c,c.return,n1)}}function cr(e){var c=e.updateQueue;if(c!==null){var n=e.stateNode;try{Pn(c,n)}catch(o){i2(e,e.return,o)}}}function ar(e,c,n){n.props=s6(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(o){i2(e,c,o)}}function n8(e,c){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var o=e.stateNode;break;case 30:o=e.stateNode;break;default:o=e.stateNode}typeof n=="function"?e.refCleanup=n(o):n.current=o}}catch(d){i2(e,c,d)}}function U4(e,c){var n=e.ref,o=e.refCleanup;if(n!==null)if(typeof o=="function")try{o()}catch(d){i2(e,c,d)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n=="function")try{n(null)}catch(d){i2(e,c,d)}else n.current=null}function nr(e){var c=e.type,n=e.memoizedProps,o=e.stateNode;try{t:switch(c){case"button":case"input":case"select":case"textarea":n.autoFocus&&o.focus();break t;case"img":n.src?o.src=n.src:n.srcSet&&(o.srcset=n.srcSet)}}catch(d){i2(e,e.return,d)}}function $7(e,c,n){try{var o=e.stateNode;Cf(o,e.type,n,c),o[X2]=c}catch(d){i2(e,e.return,d)}}function lr(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&_3(e.type)||e.tag===4}function Z7(e){t:for(;;){for(;e.sibling===null;){if(e.return===null||lr(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&_3(e.type)||e.flags&2||e.child===null||e.tag===4)continue t;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function P7(e,c,n){var o=e.tag;if(o===5||o===6)e=e.stateNode,c?(n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n).insertBefore(e,c):(c=n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n,c.appendChild(e),n=n._reactRootContainer,n!=null||c.onclick!==null||(c.onclick=K4));else if(o!==4&&(o===27&&_3(e.type)&&(n=e.stateNode,c=null),e=e.child,e!==null))for(P7(e,c,n),e=e.sibling;e!==null;)P7(e,c,n),e=e.sibling}function E5(e,c,n){var o=e.tag;if(o===5||o===6)e=e.stateNode,c?n.insertBefore(e,c):n.appendChild(e);else if(o!==4&&(o===27&&_3(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(E5(e,c,n),e=e.sibling;e!==null;)E5(e,c,n),e=e.sibling}function rr(e){var c=e.stateNode,n=e.memoizedProps;try{for(var o=e.type,d=c.attributes;d.length;)c.removeAttributeNode(d[0]);Z2(c,o,n),c[O2]=e,c[X2]=n}catch(v){i2(e,e.return,v)}}var l3=!1,F2=!1,G7=!1,ir=typeof WeakSet=="function"?WeakSet:Set,_2=null;function cf(e,c){if(e=e.containerInfo,m9=at,e=zn(e),De(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else t:{n=(n=e.ownerDocument)&&n.defaultView||window;var o=n.getSelection&&n.getSelection();if(o&&o.rangeCount!==0){n=o.anchorNode;var d=o.anchorOffset,v=o.focusNode;o=o.focusOffset;try{n.nodeType,v.nodeType}catch{n=null;break t}var M=0,N=-1,D=-1,Q=0,n1=0,o1=e,X=null;e:for(;;){for(var t1;o1!==n||d!==0&&o1.nodeType!==3||(N=M+d),o1!==v||o!==0&&o1.nodeType!==3||(D=M+o),o1.nodeType===3&&(M+=o1.nodeValue.length),(t1=o1.firstChild)!==null;)X=o1,o1=t1;for(;;){if(o1===e)break e;if(X===n&&++Q===d&&(N=M),X===v&&++n1===o&&(D=M),(t1=o1.nextSibling)!==null)break;o1=X,X=o1.parentNode}o1=t1}n=N===-1||D===-1?null:{start:N,end:D}}else n=null}n=n||{start:0,end:0}}else n=null;for(v9={focusedElem:e,selectionRange:n},at=!1,_2=c;_2!==null;)if(c=_2,e=c.child,(c.subtreeFlags&1028)!==0&&e!==null)e.return=c,_2=e;else for(;_2!==null;){switch(c=_2,v=c.alternate,e=c.flags,c.tag){case 0:if((e&4)!==0&&(e=c.updateQueue,e=e!==null?e.events:null,e!==null))for(n=0;n title"))),Z2(v,o,n),v[O2]=e,q2(v),o=v;break t;case"link":var M=fi("link","href",d).get(o+(n.href||""));if(M){for(var N=0;Nd2&&(M=d2,d2=R1,R1=M);var P=gn(N,R1),I=gn(N,d2);if(P&&I&&(t1.rangeCount!==1||t1.anchorNode!==P.node||t1.anchorOffset!==P.offset||t1.focusNode!==I.node||t1.focusOffset!==I.offset)){var Y=o1.createRange();Y.setStart(P.node,P.offset),t1.removeAllRanges(),R1>d2?(t1.addRange(Y),t1.extend(I.node,I.offset)):(Y.setEnd(I.node,I.offset),t1.addRange(Y))}}}}for(o1=[],t1=N;t1=t1.parentNode;)t1.nodeType===1&&o1.push({element:t1,left:t1.scrollLeft,top:t1.scrollTop});for(typeof N.focus=="function"&&N.focus(),N=0;Nn?32:n,k.T=null,n=t9,t9=null;var v=E3,M=u3;if(E2=0,W6=E3=null,u3=0,(n2&6)!==0)throw Error(i(331));var N=n2;if(n2|=4,xr(v.current),vr(v,v.current,M,n),n2=N,u8(0,!1),M2&&typeof M2.onPostCommitFiberRoot=="function")try{M2.onPostCommitFiberRoot(o2,v)}catch{}return!0}finally{$.p=d,k.T=o,Er(e,c)}}function qr(e,c,n){c=x4(n,c),c=F7(e.stateNode,c,2),e=L3(e,c,2),e!==null&&(B0(e,2),I4(e))}function i2(e,c,n){if(e.tag===3)qr(e,e,n);else for(;c!==null;){if(c.tag===3){qr(c,e,n);break}else if(c.tag===1){var o=c.stateNode;if(typeof c.type.getDerivedStateFromError=="function"||typeof o.componentDidCatch=="function"&&(R3===null||!R3.has(o))){e=x4(n,e),n=_l(2),o=L3(c,n,2),o!==null&&(Dl(n,o,c,e),B0(o,2),I4(o));break}}c=c.return}}function n9(e,c,n){var o=e.pingCache;if(o===null){o=e.pingCache=new lf;var d=new Set;o.set(c,d)}else d=o.get(c),d===void 0&&(d=new Set,o.set(c,d));d.has(n)||(Q7=!0,d.add(n),e=hf.bind(null,e,c,n),c.then(e,e))}function hf(e,c,n){var o=e.pingCache;o!==null&&o.delete(c),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,m2===e&&(X1&n)===n&&(C2===4||C2===3&&(X1&62914560)===X1&&300>x1()-_5?(n2&2)===0&&t0(e,0):X7|=n,J6===X1&&(J6=0)),I4(e)}function _r(e,c){c===0&&(c=ja()),e=J3(e,c),e!==null&&(B0(e,c),I4(e))}function df(e){var c=e.memoizedState,n=0;c!==null&&(n=c.retryLane),_r(e,n)}function ff(e,c){var n=0;switch(e.tag){case 31:case 13:var o=e.stateNode,d=e.memoizedState;d!==null&&(n=d.retryLane);break;case 19:o=e.stateNode;break;case 22:o=e.stateNode._retryCache;break;default:throw Error(i(314))}o!==null&&o.delete(c),_r(e,n)}function mf(e,c){return d1(e,c)}var P5=null,c0=null,l9=!1,G5=!1,r9=!1,q3=0;function I4(e){e!==c0&&e.next===null&&(c0===null?P5=c0=e:c0=c0.next=e),G5=!0,l9||(l9=!0,pf())}function u8(e,c){if(!r9&&G5){r9=!0;do for(var n=!1,o=P5;o!==null;){if(e!==0){var d=o.pendingLanes;if(d===0)var v=0;else{var M=o.suspendedLanes,N=o.pingedLanes;v=(1<<31-y1(42|e)+1)-1,v&=d&~(M&~N),v=v&201326741?v&201326741|1:v?v|2:0}v!==0&&(n=!0,Ir(o,v))}else v=X1,v=y2(o,o===m2?v:0,o.cancelPendingCommit!==null||o.timeoutHandle!==-1),(v&3)===0||B4(o,v)||(n=!0,Ir(o,v));o=o.next}while(n);r9=!1}}function vf(){Dr()}function Dr(){G5=l9=!1;var e=0;q3!==0&&Hf()&&(e=q3);for(var c=x1(),n=null,o=P5;o!==null;){var d=o.next,v=Or(o,c);v===0?(o.next=null,n===null?P5=d:n.next=d,d===null&&(c0=n)):(n=o,(e!==0||(v&3)!==0)&&(G5=!0)),o=d}E2!==0&&E2!==5||u8(e),q3!==0&&(q3=0)}function Or(e,c){for(var n=e.suspendedLanes,o=e.pingedLanes,d=e.expirationTimes,v=e.pendingLanes&-62914561;0N)break;var n1=D.transferSize,o1=D.initiatorType;n1&&Xr(o1)&&(D=D.responseEnd,M+=n1*(D"u"?null:document;function oi(e,c,n){var o=a0;if(o&&typeof c=="string"&&c){var d=p4(c);d='link[rel="'+e+'"][href="'+d+'"]',typeof n=="string"&&(d+='[crossorigin="'+n+'"]'),si.has(d)||(si.add(d),e={rel:e,crossOrigin:n,href:c},o.querySelector(d)===null&&(c=o.createElement("link"),Z2(c,"link",e),q2(c),o.head.appendChild(c)))}}function Rf(e){h3.D(e),oi("dns-prefetch",e,null)}function Ef(e,c){h3.C(e,c),oi("preconnect",e,c)}function Tf(e,c,n){h3.L(e,c,n);var o=a0;if(o&&e&&c){var d='link[rel="preload"][as="'+p4(c)+'"]';c==="image"&&n&&n.imageSrcSet?(d+='[imagesrcset="'+p4(n.imageSrcSet)+'"]',typeof n.imageSizes=="string"&&(d+='[imagesizes="'+p4(n.imageSizes)+'"]')):d+='[href="'+p4(e)+'"]';var v=d;switch(c){case"style":v=n0(e);break;case"script":v=l0(e)}C4.has(v)||(e=b({rel:"preload",href:c==="image"&&n&&n.imageSrcSet?void 0:e,as:c},n),C4.set(v,e),o.querySelector(d)!==null||c==="style"&&o.querySelector(m8(v))||c==="script"&&o.querySelector(v8(v))||(c=o.createElement("link"),Z2(c,"link",e),q2(c),o.head.appendChild(c)))}}function qf(e,c){h3.m(e,c);var n=a0;if(n&&e){var o=c&&typeof c.as=="string"?c.as:"script",d='link[rel="modulepreload"][as="'+p4(o)+'"][href="'+p4(e)+'"]',v=d;switch(o){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":v=l0(e)}if(!C4.has(v)&&(e=b({rel:"modulepreload",href:e},c),C4.set(v,e),n.querySelector(d)===null)){switch(o){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(n.querySelector(v8(v)))return}o=n.createElement("link"),Z2(o,"link",e),q2(o),n.head.appendChild(o)}}}function _f(e,c,n){h3.S(e,c,n);var o=a0;if(o&&e){var d=H6(o).hoistableStyles,v=n0(e);c=c||"default";var M=d.get(v);if(!M){var N={loading:0,preload:null};if(M=o.querySelector(m8(v)))N.loading=5;else{e=b({rel:"stylesheet",href:e,"data-precedence":c},n),(n=C4.get(v))&&y9(e,n);var D=M=o.createElement("link");q2(D),Z2(D,"link",e),D._p=new Promise(function(Q,n1){D.onload=Q,D.onerror=n1}),D.addEventListener("load",function(){N.loading|=1}),D.addEventListener("error",function(){N.loading|=2}),N.loading|=4,J5(M,c,o)}M={type:"stylesheet",instance:M,count:1,state:N},d.set(v,M)}}}function Df(e,c){h3.X(e,c);var n=a0;if(n&&e){var o=H6(n).hoistableScripts,d=l0(e),v=o.get(d);v||(v=n.querySelector(v8(d)),v||(e=b({src:e,async:!0},c),(c=C4.get(d))&&w9(e,c),v=n.createElement("script"),q2(v),Z2(v,"link",e),n.head.appendChild(v)),v={type:"script",instance:v,count:1,state:null},o.set(d,v))}}function Of(e,c){h3.M(e,c);var n=a0;if(n&&e){var o=H6(n).hoistableScripts,d=l0(e),v=o.get(d);v||(v=n.querySelector(v8(d)),v||(e=b({src:e,async:!0,type:"module"},c),(c=C4.get(d))&&w9(e,c),v=n.createElement("script"),q2(v),Z2(v,"link",e),n.head.appendChild(v)),v={type:"script",instance:v,count:1,state:null},o.set(d,v))}}function ui(e,c,n,o){var d=(d=z1.current)?X5(d):null;if(!d)throw Error(i(446));switch(e){case"meta":case"title":return null;case"style":return typeof n.precedence=="string"&&typeof n.href=="string"?(c=n0(n.href),n=H6(d).hoistableStyles,o=n.get(c),o||(o={type:"style",instance:null,count:0,state:null},n.set(c,o)),o):{type:"void",instance:null,count:0,state:null};case"link":if(n.rel==="stylesheet"&&typeof n.href=="string"&&typeof n.precedence=="string"){e=n0(n.href);var v=H6(d).hoistableStyles,M=v.get(e);if(M||(d=d.ownerDocument||d,M={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},v.set(e,M),(v=d.querySelector(m8(e)))&&!v._p&&(M.instance=v,M.state.loading=5),C4.has(e)||(n={rel:"preload",as:"style",href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},C4.set(e,n),v||Uf(d,e,n,M.state))),c&&o===null)throw Error(i(528,""));return M}if(c&&o!==null)throw Error(i(529,""));return null;case"script":return c=n.async,n=n.src,typeof n=="string"&&c&&typeof c!="function"&&typeof c!="symbol"?(c=l0(n),n=H6(d).hoistableScripts,o=n.get(c),o||(o={type:"script",instance:null,count:0,state:null},n.set(c,o)),o):{type:"void",instance:null,count:0,state:null};default:throw Error(i(444,e))}}function n0(e){return'href="'+p4(e)+'"'}function m8(e){return'link[rel="stylesheet"]['+e+"]"}function hi(e){return b({},e,{"data-precedence":e.precedence,precedence:null})}function Uf(e,c,n,o){e.querySelector('link[rel="preload"][as="style"]['+c+"]")?o.loading=1:(c=e.createElement("link"),o.preload=c,c.addEventListener("load",function(){return o.loading|=1}),c.addEventListener("error",function(){return o.loading|=2}),Z2(c,"link",n),q2(c),e.head.appendChild(c))}function l0(e){return'[src="'+p4(e)+'"]'}function v8(e){return"script[async]"+e}function di(e,c,n){if(c.count++,c.instance===null)switch(c.type){case"style":var o=e.querySelector('style[data-href~="'+p4(n.href)+'"]');if(o)return c.instance=o,q2(o),o;var d=b({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return o=(e.ownerDocument||e).createElement("style"),q2(o),Z2(o,"style",d),J5(o,n.precedence,e),c.instance=o;case"stylesheet":d=n0(n.href);var v=e.querySelector(m8(d));if(v)return c.state.loading|=4,c.instance=v,q2(v),v;o=hi(n),(d=C4.get(d))&&y9(o,d),v=(e.ownerDocument||e).createElement("link"),q2(v);var M=v;return M._p=new Promise(function(N,D){M.onload=N,M.onerror=D}),Z2(v,"link",o),c.state.loading|=4,J5(v,n.precedence,e),c.instance=v;case"script":return v=l0(n.src),(d=e.querySelector(v8(v)))?(c.instance=d,q2(d),d):(o=n,(d=C4.get(v))&&(o=b({},n),w9(o,d)),e=e.ownerDocument||e,d=e.createElement("script"),q2(d),Z2(d,"link",o),e.head.appendChild(d),c.instance=d);case"void":return null;default:throw Error(i(443,c.type))}else c.type==="stylesheet"&&(c.state.loading&4)===0&&(o=c.instance,c.state.loading|=4,J5(o,n.precedence,e));return c.instance}function J5(e,c,n){for(var o=n.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),d=o.length?o[o.length-1]:null,v=d,M=0;M title"):null)}function If(e,c,n){if(n===1||c.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof c.precedence!="string"||typeof c.href!="string"||c.href==="")break;return!0;case"link":if(typeof c.rel!="string"||typeof c.href!="string"||c.href===""||c.onLoad||c.onError)break;switch(c.rel){case"stylesheet":return e=c.disabled,typeof c.precedence=="string"&&e==null;default:return!0}case"script":if(c.async&&typeof c.async!="function"&&typeof c.async!="symbol"&&!c.onLoad&&!c.onError&&c.src&&typeof c.src=="string")return!0}return!1}function vi(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function $f(e,c,n,o){if(n.type==="stylesheet"&&(typeof o.media!="string"||matchMedia(o.media).matches!==!1)&&(n.state.loading&4)===0){if(n.instance===null){var d=n0(o.href),v=c.querySelector(m8(d));if(v){c=v._p,c!==null&&typeof c=="object"&&typeof c.then=="function"&&(e.count++,e=tt.bind(e),c.then(e,e)),n.state.loading|=4,n.instance=v,q2(v);return}v=c.ownerDocument||c,o=hi(o),(d=C4.get(d))&&y9(o,d),v=v.createElement("link"),q2(v);var M=v;M._p=new Promise(function(N,D){M.onload=N,M.onerror=D}),Z2(v,"link",o),n.instance=v}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,c),(c=n.state.preload)&&(n.state.loading&3)===0&&(e.count++,n=tt.bind(e),c.addEventListener("load",n),c.addEventListener("error",n))}}var C9=0;function Zf(e,c){return e.stylesheets&&e.count===0&&ct(e,e.stylesheets),0C9?50:800)+c);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(o),clearTimeout(d)}}:null}function tt(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)ct(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var et=null;function ct(e,c){e.stylesheets=null,e.unsuspend!==null&&(e.count++,et=new Map,c.forEach(Pf,e),et=null,tt.call(e))}function Pf(e,c){if(!(c.state.loading&4)){var n=et.get(e);if(n)var o=n.get(null);else{n=new Map,et.set(e,n);for(var d=e.querySelectorAll("link[data-precedence],style[data-precedence]"),v=0;v"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(a){console.error(a)}}return t(),F9.exports=sm(),F9.exports}var um=om();var _i="popstate";function hm(t={}){function a(i,u){let{pathname:h,search:m,hash:p}=i.location;return bc("",{pathname:h,search:m,hash:p},u.state&&u.state.usr||null,u.state&&u.state.key||"default")}function l(i,u){return typeof u=="string"?u:k8(u)}return fm(a,l,null,t)}function z2(t,a){if(t===!1||t===null||typeof t>"u")throw new Error(a)}function q4(t,a){if(!t){typeof console<"u"&&console.warn(a);try{throw new Error(a)}catch{}}}function dm(){return Math.random().toString(36).substring(2,10)}function Di(t,a){return{usr:t.state,key:t.key,idx:a}}function bc(t,a,l=null,i){return{pathname:typeof t=="string"?t:t.pathname,search:"",hash:"",...typeof a=="string"?C0(a):a,state:l,key:a&&a.key||i||dm()}}function k8({pathname:t="/",search:a="",hash:l=""}){return a&&a!=="?"&&(t+=a.charAt(0)==="?"?a:"?"+a),l&&l!=="#"&&(t+=l.charAt(0)==="#"?l:"#"+l),t}function C0(t){let a={};if(t){let l=t.indexOf("#");l>=0&&(a.hash=t.substring(l),t=t.substring(0,l));let i=t.indexOf("?");i>=0&&(a.search=t.substring(i),t=t.substring(0,i)),t&&(a.pathname=t)}return a}function fm(t,a,l,i={}){let{window:u=document.defaultView,v5Compat:h=!1}=i,m=u.history,p="POP",x=null,z=g();z==null&&(z=0,m.replaceState({...m.state,idx:z},""));function g(){return(m.state||{idx:null}).idx}function b(){p="POP";let C=g(),L=C==null?null:C-z;z=C,x&&x({action:p,location:S.location,delta:L})}function y(C,L){p="PUSH";let V=bc(S.location,C,L);z=g()+1;let A=Di(V,z),F=S.createHref(V);try{m.pushState(A,"",F)}catch(T){if(T instanceof DOMException&&T.name==="DataCloneError")throw T;u.location.assign(F)}h&&x&&x({action:p,location:S.location,delta:1})}function w(C,L){p="REPLACE";let V=bc(S.location,C,L);z=g();let A=Di(V,z),F=S.createHref(V);m.replaceState(A,"",F),h&&x&&x({action:p,location:S.location,delta:0})}function H(C){return mm(C)}let S={get action(){return p},get location(){return t(u,m)},listen(C){if(x)throw new Error("A history only accepts one active listener");return u.addEventListener(_i,b),x=C,()=>{u.removeEventListener(_i,b),x=null}},createHref(C){return a(u,C)},createURL:H,encodeLocation(C){let L=H(C);return{pathname:L.pathname,search:L.search,hash:L.hash}},push:y,replace:w,go(C){return m.go(C)}};return S}function mm(t,a=!1){let l="http://localhost";typeof window<"u"&&(l=window.location.origin!=="null"?window.location.origin:window.location.href),z2(l,"No window.location.(origin|href) available to create URL");let i=typeof t=="string"?t:k8(t);return i=i.replace(/ $/,"%20"),!a&&i.startsWith("//")&&(i=l+i),new URL(i,l)}function So(t,a,l="/"){return vm(t,a,l,!1)}function vm(t,a,l,i){let u=typeof a=="string"?C0(a):a,h=z3(u.pathname||"/",l);if(h==null)return null;let m=Ho(t);pm(m);let p=null;for(let x=0;p==null&&x{let g={relativePath:z===void 0?m.path||"":z,caseSensitive:m.caseSensitive===!0,childrenIndex:p,route:m};if(g.relativePath.startsWith("/")){if(!g.relativePath.startsWith(i)&&x)return;z2(g.relativePath.startsWith(i),`Absolute route path "${g.relativePath}" nested under path "${i}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),g.relativePath=g.relativePath.slice(i.length)}let b=g3([i,g.relativePath]),y=l.concat(g);m.children&&m.children.length>0&&(z2(m.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${b}".`),Ho(m.children,a,y,b,x)),!(m.path==null&&!m.index)&&a.push({path:b,score:wm(b,m.index),routesMeta:y})};return t.forEach((m,p)=>{if(m.path===""||!m.path?.includes("?"))h(m,p);else for(let x of Ao(m.path))h(m,p,!0,x)}),a}function Ao(t){let a=t.split("/");if(a.length===0)return[];let[l,...i]=a,u=l.endsWith("?"),h=l.replace(/\?$/,"");if(i.length===0)return u?[h,""]:[h];let m=Ao(i.join("/")),p=[];return p.push(...m.map(x=>x===""?h:[h,x].join("/"))),u&&p.push(...m),p.map(x=>t.startsWith("/")&&x===""?"/":x)}function pm(t){t.sort((a,l)=>a.score!==l.score?l.score-a.score:Cm(a.routesMeta.map(i=>i.childrenIndex),l.routesMeta.map(i=>i.childrenIndex)))}var gm=/^:[\w-]+$/,xm=3,zm=2,bm=1,Mm=10,ym=-2,Oi=t=>t==="*";function wm(t,a){let l=t.split("/"),i=l.length;return l.some(Oi)&&(i+=ym),a&&(i+=zm),l.filter(u=>!Oi(u)).reduce((u,h)=>u+(gm.test(h)?xm:h===""?bm:Mm),i)}function Cm(t,a){return t.length===a.length&&t.slice(0,-1).every((i,u)=>i===a[u])?t[t.length-1]-a[a.length-1]:0}function Sm(t,a,l=!1){let{routesMeta:i}=t,u={},h="/",m=[];for(let p=0;p{if(g==="*"){let H=p[y]||"";m=h.slice(0,h.length-H.length).replace(/(.)\/+$/,"$1")}const w=p[y];return b&&!w?z[g]=void 0:z[g]=(w||"").replace(/%2F/g,"/"),z},{}),pathname:h,pathnameBase:m,pattern:t}}function Hm(t,a=!1,l=!0){q4(t==="*"||!t.endsWith("*")||t.endsWith("/*"),`Route path "${t}" will be treated as if it were "${t.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${t.replace(/\*$/,"/*")}".`);let i=[],u="^"+t.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(m,p,x)=>(i.push({paramName:p,isOptional:x!=null}),x?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return t.endsWith("*")?(i.push({paramName:"*"}),u+=t==="*"||t==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):l?u+="\\/*$":t!==""&&t!=="/"&&(u+="(?:(?=\\/|$))"),[new RegExp(u,a?void 0:"i"),i]}function Am(t){try{return t.split("/").map(a=>decodeURIComponent(a).replace(/\//g,"%2F")).join("/")}catch(a){return q4(!1,`The URL path "${t}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${a}).`),t}}function z3(t,a){if(a==="/")return t;if(!t.toLowerCase().startsWith(a.toLowerCase()))return null;let l=a.endsWith("/")?a.length-1:a.length,i=t.charAt(l);return i&&i!=="/"?null:t.slice(l)||"/"}var Vm=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Lm=t=>Vm.test(t);function Bm(t,a="/"){let{pathname:l,search:i="",hash:u=""}=typeof t=="string"?C0(t):t,h;if(l)if(Lm(l))h=l;else{if(l.includes("//")){let m=l;l=l.replace(/\/\/+/g,"/"),q4(!1,`Pathnames cannot have embedded double slashes - normalizing ${m} -> ${l}`)}l.startsWith("/")?h=Ui(l.substring(1),"/"):h=Ui(l,a)}else h=a;return{pathname:h,search:Fm(i),hash:km(u)}}function Ui(t,a){let l=a.replace(/\/+$/,"").split("/");return t.split("/").forEach(u=>{u===".."?l.length>1&&l.pop():u!=="."&&l.push(u)}),l.length>1?l.join("/"):"/"}function T9(t,a,l,i){return`Cannot include a '${t}' character in a manually specified \`to.${a}\` field [${JSON.stringify(i)}]. Please separate it out to the \`to.${l}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function Nm(t){return t.filter((a,l)=>l===0||a.route.path&&a.route.path.length>0)}function Vo(t){let a=Nm(t);return a.map((l,i)=>i===a.length-1?l.pathname:l.pathnameBase)}function Lo(t,a,l,i=!1){let u;typeof t=="string"?u=C0(t):(u={...t},z2(!u.pathname||!u.pathname.includes("?"),T9("?","pathname","search",u)),z2(!u.pathname||!u.pathname.includes("#"),T9("#","pathname","hash",u)),z2(!u.search||!u.search.includes("#"),T9("#","search","hash",u)));let h=t===""||u.pathname==="",m=h?"/":u.pathname,p;if(m==null)p=l;else{let b=a.length-1;if(!i&&m.startsWith("..")){let y=m.split("/");for(;y[0]==="..";)y.shift(),b-=1;u.pathname=y.join("/")}p=b>=0?a[b]:"/"}let x=Bm(u,p),z=m&&m!=="/"&&m.endsWith("/"),g=(h||m===".")&&l.endsWith("/");return!x.pathname.endsWith("/")&&(z||g)&&(x.pathname+="/"),x}var g3=t=>t.join("/").replace(/\/\/+/g,"/"),jm=t=>t.replace(/\/+$/,"").replace(/^\/*/,"/"),Fm=t=>!t||t==="?"?"":t.startsWith("?")?t:"?"+t,km=t=>!t||t==="#"?"":t.startsWith("#")?t:"#"+t;function Rm(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.internal=="boolean"&&"data"in t}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Bo=["POST","PUT","PATCH","DELETE"];new Set(Bo);var Em=["GET",...Bo];new Set(Em);var S0=f.createContext(null);S0.displayName="DataRouter";var le=f.createContext(null);le.displayName="DataRouterState";f.createContext(!1);var No=f.createContext({isTransitioning:!1});No.displayName="ViewTransition";var Tm=f.createContext(new Map);Tm.displayName="Fetchers";var qm=f.createContext(null);qm.displayName="Await";var P4=f.createContext(null);P4.displayName="Navigation";var U8=f.createContext(null);U8.displayName="Location";var b3=f.createContext({outlet:null,matches:[],isDataRoute:!1});b3.displayName="Route";var $c=f.createContext(null);$c.displayName="RouteError";function _m(t,{relative:a}={}){z2(I8(),"useHref() may be used only in the context of a component.");let{basename:l,navigator:i}=f.useContext(P4),{hash:u,pathname:h,search:m}=$8(t,{relative:a}),p=h;return l!=="/"&&(p=h==="/"?l:g3([l,h])),i.createHref({pathname:p,search:m,hash:u})}function I8(){return f.useContext(U8)!=null}function G3(){return z2(I8(),"useLocation() may be used only in the context of a component."),f.useContext(U8).location}var jo="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Fo(t){f.useContext(P4).static||f.useLayoutEffect(t)}function Dm(){let{isDataRoute:t}=f.useContext(b3);return t?Wm():Om()}function Om(){z2(I8(),"useNavigate() may be used only in the context of a component.");let t=f.useContext(S0),{basename:a,navigator:l}=f.useContext(P4),{matches:i}=f.useContext(b3),{pathname:u}=G3(),h=JSON.stringify(Vo(i)),m=f.useRef(!1);return Fo(()=>{m.current=!0}),f.useCallback((x,z={})=>{if(q4(m.current,jo),!m.current)return;if(typeof x=="number"){l.go(x);return}let g=Lo(x,JSON.parse(h),u,z.relative==="path");t==null&&a!=="/"&&(g.pathname=g.pathname==="/"?a:g3([a,g.pathname])),(z.replace?l.replace:l.push)(g,z.state,z)},[a,l,h,u,t])}f.createContext(null);function $8(t,{relative:a}={}){let{matches:l}=f.useContext(b3),{pathname:i}=G3(),u=JSON.stringify(Vo(l));return f.useMemo(()=>Lo(t,JSON.parse(u),i,a==="path"),[t,u,i,a])}function Um(t,a){return ko(t,a)}function ko(t,a,l,i,u){z2(I8(),"useRoutes() may be used only in the context of a component.");let{navigator:h}=f.useContext(P4),{matches:m}=f.useContext(b3),p=m[m.length-1],x=p?p.params:{},z=p?p.pathname:"/",g=p?p.pathnameBase:"/",b=p&&p.route;{let V=b&&b.path||"";Ro(z,!b||V.endsWith("*")||V.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${z}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let y=G3(),w;if(a){let V=typeof a=="string"?C0(a):a;z2(g==="/"||V.pathname?.startsWith(g),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${g}" but pathname "${V.pathname}" was given in the \`location\` prop.`),w=V}else w=y;let H=w.pathname||"/",S=H;if(g!=="/"){let V=g.replace(/^\//,"").split("/");S="/"+H.replace(/^\//,"").split("/").slice(V.length).join("/")}let C=So(t,{pathname:S});q4(b||C!=null,`No routes matched location "${w.pathname}${w.search}${w.hash}" `),q4(C==null||C[C.length-1].route.element!==void 0||C[C.length-1].route.Component!==void 0||C[C.length-1].route.lazy!==void 0,`Matched leaf route at location "${w.pathname}${w.search}${w.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let L=Gm(C&&C.map(V=>Object.assign({},V,{params:Object.assign({},x,V.params),pathname:g3([g,h.encodeLocation?h.encodeLocation(V.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:V.pathname]),pathnameBase:V.pathnameBase==="/"?g:g3([g,h.encodeLocation?h.encodeLocation(V.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:V.pathnameBase])})),m,l,i,u);return a&&L?f.createElement(U8.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...w},navigationType:"POP"}},L):L}function Im(){let t=Jm(),a=Rm(t)?`${t.status} ${t.statusText}`:t instanceof Error?t.message:JSON.stringify(t),l=t instanceof Error?t.stack:null,i="rgba(200,200,200, 0.5)",u={padding:"0.5rem",backgroundColor:i},h={padding:"2px 4px",backgroundColor:i},m=null;return console.error("Error handled by React Router default ErrorBoundary:",t),m=f.createElement(f.Fragment,null,f.createElement("p",null,"💿 Hey developer 👋"),f.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",f.createElement("code",{style:h},"ErrorBoundary")," or"," ",f.createElement("code",{style:h},"errorElement")," prop on your route.")),f.createElement(f.Fragment,null,f.createElement("h2",null,"Unexpected Application Error!"),f.createElement("h3",{style:{fontStyle:"italic"}},a),l?f.createElement("pre",{style:u},l):null,m)}var $m=f.createElement(Im,null),Zm=class extends f.Component{constructor(t){super(t),this.state={location:t.location,revalidation:t.revalidation,error:t.error}}static getDerivedStateFromError(t){return{error:t}}static getDerivedStateFromProps(t,a){return a.location!==t.location||a.revalidation!=="idle"&&t.revalidation==="idle"?{error:t.error,location:t.location,revalidation:t.revalidation}:{error:t.error!==void 0?t.error:a.error,location:a.location,revalidation:t.revalidation||a.revalidation}}componentDidCatch(t,a){this.props.onError?this.props.onError(t,a):console.error("React Router caught the following error during render",t)}render(){return this.state.error!==void 0?f.createElement(b3.Provider,{value:this.props.routeContext},f.createElement($c.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function Pm({routeContext:t,match:a,children:l}){let i=f.useContext(S0);return i&&i.static&&i.staticContext&&(a.route.errorElement||a.route.ErrorBoundary)&&(i.staticContext._deepestRenderedBoundaryId=a.route.id),f.createElement(b3.Provider,{value:t},l)}function Gm(t,a=[],l=null,i=null,u=null){if(t==null){if(!l)return null;if(l.errors)t=l.matches;else if(a.length===0&&!l.initialized&&l.matches.length>0)t=l.matches;else return null}let h=t,m=l?.errors;if(m!=null){let g=h.findIndex(b=>b.route.id&&m?.[b.route.id]!==void 0);z2(g>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(m).join(",")}`),h=h.slice(0,Math.min(h.length,g+1))}let p=!1,x=-1;if(l)for(let g=0;g=0?h=h.slice(0,x+1):h=[h[0]];break}}}let z=l&&i?(g,b)=>{i(g,{location:l.location,params:l.matches?.[0]?.params??{},errorInfo:b})}:void 0;return h.reduceRight((g,b,y)=>{let w,H=!1,S=null,C=null;l&&(w=m&&b.route.id?m[b.route.id]:void 0,S=b.route.errorElement||$m,p&&(x<0&&y===0?(Ro("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),H=!0,C=null):x===y&&(H=!0,C=b.route.hydrateFallbackElement||null)));let L=a.concat(h.slice(0,y+1)),V=()=>{let A;return w?A=S:H?A=C:b.route.Component?A=f.createElement(b.route.Component,null):b.route.element?A=b.route.element:A=g,f.createElement(Pm,{match:b,routeContext:{outlet:g,matches:L,isDataRoute:l!=null},children:A})};return l&&(b.route.ErrorBoundary||b.route.errorElement||y===0)?f.createElement(Zm,{location:l.location,revalidation:l.revalidation,component:S,error:w,children:V(),routeContext:{outlet:null,matches:L,isDataRoute:!0},onError:z}):V()},null)}function Zc(t){return`${t} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Ym(t){let a=f.useContext(S0);return z2(a,Zc(t)),a}function Km(t){let a=f.useContext(le);return z2(a,Zc(t)),a}function Qm(t){let a=f.useContext(b3);return z2(a,Zc(t)),a}function Pc(t){let a=Qm(t),l=a.matches[a.matches.length-1];return z2(l.route.id,`${t} can only be used on routes that contain a unique "id"`),l.route.id}function Xm(){return Pc("useRouteId")}function Jm(){let t=f.useContext($c),a=Km("useRouteError"),l=Pc("useRouteError");return t!==void 0?t:a.errors?.[l]}function Wm(){let{router:t}=Ym("useNavigate"),a=Pc("useNavigate"),l=f.useRef(!1);return Fo(()=>{l.current=!0}),f.useCallback(async(u,h={})=>{q4(l.current,jo),l.current&&(typeof u=="number"?t.navigate(u):await t.navigate(u,{fromRouteId:a,...h}))},[t,a])}var Ii={};function Ro(t,a,l){!a&&!Ii[t]&&(Ii[t]=!0,q4(!1,l))}f.memo(tv);function tv({routes:t,future:a,state:l,unstable_onError:i}){return ko(t,void 0,l,i,a)}function m0(t){z2(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function ev({basename:t="/",children:a=null,location:l,navigationType:i="POP",navigator:u,static:h=!1}){z2(!I8(),"You cannot render a inside another . You should never have more than one in your app.");let m=t.replace(/^\/*/,"/"),p=f.useMemo(()=>({basename:m,navigator:u,static:h,future:{}}),[m,u,h]);typeof l=="string"&&(l=C0(l));let{pathname:x="/",search:z="",hash:g="",state:b=null,key:y="default"}=l,w=f.useMemo(()=>{let H=z3(x,m);return H==null?null:{location:{pathname:H,search:z,hash:g,state:b,key:y},navigationType:i}},[m,x,z,g,b,y,i]);return q4(w!=null,` is not able to match the URL "${x}${z}${g}" because it does not start with the basename, so the won't render anything.`),w==null?null:f.createElement(P4.Provider,{value:p},f.createElement(U8.Provider,{children:a,value:w}))}function cv({children:t,location:a}){return Um(Mc(t),a)}function Mc(t,a=[]){let l=[];return f.Children.forEach(t,(i,u)=>{if(!f.isValidElement(i))return;let h=[...a,u];if(i.type===f.Fragment){l.push.apply(l,Mc(i.props.children,h));return}z2(i.type===m0,`[${typeof i.type=="string"?i.type:i.type.name}] is not a component. All component children of must be a or `),z2(!i.props.index||!i.props.children,"An index route cannot have child routes.");let m={id:i.props.id||h.join("-"),caseSensitive:i.props.caseSensitive,element:i.props.element,Component:i.props.Component,index:i.props.index,path:i.props.path,middleware:i.props.middleware,loader:i.props.loader,action:i.props.action,hydrateFallbackElement:i.props.hydrateFallbackElement,HydrateFallback:i.props.HydrateFallback,errorElement:i.props.errorElement,ErrorBoundary:i.props.ErrorBoundary,hasErrorBoundary:i.props.hasErrorBoundary===!0||i.props.ErrorBoundary!=null||i.props.errorElement!=null,shouldRevalidate:i.props.shouldRevalidate,handle:i.props.handle,lazy:i.props.lazy};i.props.children&&(m.children=Mc(i.props.children,h)),l.push(m)}),l}var At="get",Vt="application/x-www-form-urlencoded";function re(t){return t!=null&&typeof t.tagName=="string"}function av(t){return re(t)&&t.tagName.toLowerCase()==="button"}function nv(t){return re(t)&&t.tagName.toLowerCase()==="form"}function lv(t){return re(t)&&t.tagName.toLowerCase()==="input"}function rv(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}function iv(t,a){return t.button===0&&(!a||a==="_self")&&!rv(t)}var ut=null;function sv(){if(ut===null)try{new FormData(document.createElement("form"),0),ut=!1}catch{ut=!0}return ut}var ov=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function q9(t){return t!=null&&!ov.has(t)?(q4(!1,`"${t}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${Vt}"`),null):t}function uv(t,a){let l,i,u,h,m;if(nv(t)){let p=t.getAttribute("action");i=p?z3(p,a):null,l=t.getAttribute("method")||At,u=q9(t.getAttribute("enctype"))||Vt,h=new FormData(t)}else if(av(t)||lv(t)&&(t.type==="submit"||t.type==="image")){let p=t.form;if(p==null)throw new Error('Cannot submit a + + + + + {playableParts.length ? ( +
+
+ {playableParts.map((part) => { + const checked = selectedPartSet.has(String(part.id)); + return ( + + ); + })} +
+
+ ) : ( +
No playable parts
+ )} + + + + + +
+ Playback shape +
+ + + +
+
+ +
+ {selectedFileName ? ( +
{selectedFileName}
+ ) : ( +
No Midi file selected
+ )} +
+ +
+ + +
+ + + +
+
+

Live input

+
+ +
+ + + + + + +
+
+ + +
+
+

Beeper status

+
+ + + 0} /> + + 0} /> + +
+ {message ?
{message}
: null} +
+
+ + + ); +} diff --git a/webui/src/components/vip/VipMidiBeeperCard/midiBeeperUtils.js b/webui/src/components/vip/VipMidiBeeperCard/midiBeeperUtils.js new file mode 100644 index 00000000..f7d1a735 --- /dev/null +++ b/webui/src/components/vip/VipMidiBeeperCard/midiBeeperUtils.js @@ -0,0 +1,436 @@ +// Midi Beeper utilities +// Purpose: Parses MIDI files into simple beeper note events and converts timing into Roomba song units. +// Scope: Pure helpers only; React state, browser MIDI input, and command sending live in the card component. +import { parseMidi } from 'midi-file'; +import { + DEFAULT_ARPEGGIO_NOTE_TICKS, + DEFAULT_ARPEGGIO_NOTE_LIMIT, + DEFAULT_FILE_NOTE_TICKS, + FILE_CHUNK_GAP_THRESHOLD_MS, + MAX_FILE_NOTE_TICKS, + ROOMBA_SONG_MAX_NOTES, + ROOMBA_DURATION_TICK_MS, + ROOMBA_NOTE_MAX, + ROOMBA_NOTE_MIN, +} from './constants.js'; + +function clamp(value, min, max) { + const number = Number(value); + if (!Number.isFinite(number)) return min; + return Math.max(min, Math.min(max, number)); +} + +export function clampRoombaNote(note) { + return clamp(Math.round(note), ROOMBA_NOTE_MIN, ROOMBA_NOTE_MAX); +} + +export function clampRoombaDurationTicks(ticks) { + return clamp(Math.round(ticks), 1, 255); +} + +export function roombaTicksToMs(ticks) { + return clampRoombaDurationTicks(ticks) * ROOMBA_DURATION_TICK_MS; +} + +function formatTrackLabel(index, name, noteCount, channels = []) { + const cleanName = String(name || '').trim(); + const prefix = cleanName || `Track ${index + 1}`; + const channelLabel = channels.length > 1 ? `, ${channels.length} channels` : channels.length === 1 ? ', 1 channel' : ''; + return `${prefix} (${noteCount} notes${channelLabel})`; +} + +function collectAbsoluteEvents(track = []) { + let tick = 0; + return track.map((event) => { + tick += Number(event?.deltaTime) || 0; + return { ...event, absoluteTick: tick }; + }); +} + +function createTempoMap(parsed) { + const tempoEvents = []; + + /* + MIDI tempo is global for normal format-1 files, and tempo events often sit + in track 0 while the notes live in a later track. Reading tempo changes from + every track gives selected-track playback the same timing map without + requiring server work or a heavier sequencer library. + */ + (parsed?.tracks || []).forEach((track) => { + collectAbsoluteEvents(track).forEach((event) => { + if (event.type !== 'setTempo') return; + tempoEvents.push({ + tick: event.absoluteTick, + microsecondsPerBeat: Number(event.microsecondsPerBeat) || 500000, + }); + }); + }); + + tempoEvents.sort((a, b) => a.tick - b.tick); + if (!tempoEvents.length || tempoEvents[0].tick !== 0) { + tempoEvents.unshift({ tick: 0, microsecondsPerBeat: 500000 }); + } + + return tempoEvents; +} + +function tickToMs(tick, tempoMap, ticksPerBeat) { + let elapsedMs = 0; + let previousTick = 0; + let microsecondsPerBeat = 500000; + + /* + Tempo changes are piecewise-linear: each segment uses the tempo active at + the start of that segment. This loop is intentionally small and direct + because MIDI files for this feature are expected to be short, and clarity is + more important than caching every possible tick conversion. + */ + for (const tempo of tempoMap) { + if (tempo.tick > tick) break; + const deltaTicks = Math.max(0, tempo.tick - previousTick); + elapsedMs += (deltaTicks / ticksPerBeat) * (microsecondsPerBeat / 1000); + previousTick = tempo.tick; + microsecondsPerBeat = tempo.microsecondsPerBeat; + } + + const remainingTicks = Math.max(0, tick - previousTick); + return elapsedMs + (remainingTicks / ticksPerBeat) * (microsecondsPerBeat / 1000); +} + +function extractTrackNotes(track = [], tempoMap, ticksPerBeat) { + const absoluteEvents = collectAbsoluteEvents(track); + const activeNotes = new Map(); + const notes = []; + let trackName = ''; + + absoluteEvents.forEach((event) => { + if (event.type === 'trackName' && event.text) { + trackName = String(event.text); + return; + } + + if (event.type !== 'noteOn' && event.type !== 'noteOff') return; + + const channel = Number(event.channel) || 0; + const noteNumber = Number(event.noteNumber); + if (!Number.isFinite(noteNumber)) return; + const key = `${channel}:${noteNumber}`; + const velocity = Number(event.velocity) || 0; + const isNoteStart = event.type === 'noteOn' && velocity > 0; + + if (isNoteStart) { + /* + A repeated note-on for the same note/channel before note-off is unusual + but possible. Replacing the active note keeps the parser from creating a + negative or huge duration if the file is messy. + */ + activeNotes.set(key, { + channel, + noteNumber, + startTick: event.absoluteTick, + velocity, + }); + return; + } + + const active = activeNotes.get(key); + if (!active) return; + activeNotes.delete(key); + + const startMs = tickToMs(active.startTick, tempoMap, ticksPerBeat); + const endMs = tickToMs(event.absoluteTick, tempoMap, ticksPerBeat); + notes.push({ + channel: active.channel, + noteNumber: active.noteNumber, + velocity: active.velocity, + startMs, + durationMs: Math.max(ROOMBA_DURATION_TICK_MS, endMs - startMs), + }); + }); + + notes.sort((a, b) => a.startMs - b.startMs || b.noteNumber - a.noteNumber); + return { trackName, notes }; +} + +function summarizeChannels(notes = []) { + const counts = new Map(); + + notes.forEach((note) => { + const channel = Number(note?.channel); + if (!Number.isInteger(channel)) return; + const previous = counts.get(channel) || { + noteCount: 0, + minNote: 127, + maxNote: 0, + noteTotal: 0, + }; + previous.noteCount += 1; + previous.minNote = Math.min(previous.minNote, Number(note.noteNumber) || previous.minNote); + previous.maxNote = Math.max(previous.maxNote, Number(note.noteNumber) || previous.maxNote); + previous.noteTotal += Number(note.noteNumber) || 0; + counts.set(channel, previous); + }); + + return Array.from(counts.entries()) + .sort((a, b) => a[0] - b[0]) + .map(([channel, summary]) => ({ + channel, + noteCount: summary.noteCount, + minNote: summary.minNote, + maxNote: summary.maxNote, + averageNote: summary.noteCount > 0 ? summary.noteTotal / summary.noteCount : 0, + // MIDI channels are zero-based in the file data, but musicians and most + // MIDI tools display them as 1-16. Keeping both avoids off-by-one logic in + // the UI and makes channel 10 percussion obvious. + label: `Ch ${channel + 1}`, + isPercussion: channel === 9, + })); +} + +function buildPartSourceLabel(track, channelInfo) { + const trackName = String(track?.name || '').trim(); + const trackLabel = trackName || `Track ${Number(track?.index || 0) + 1}`; + const channelLabel = channelInfo?.label || `Ch ${Number(channelInfo?.channel || 0) + 1}`; + return `${trackLabel} - ${channelLabel}`; +} + +function buildPlayableParts(tracks = []) { + const parts = []; + + tracks.forEach((track) => { + (track.channels || []).forEach((channelInfo) => { + const notes = (track.notes || []).filter((note) => Number(note.channel) === Number(channelInfo.channel)); + if (!notes.length) return; + const trackName = String(track?.name || '').trim(); + const partNumber = parts.length + 1; + const visibleLabel = trackName ? `Part ${partNumber}: ${trackName}` : `Part ${partNumber}`; + + /* + A "part" is the user-facing musical unit. Internally it is still the + MIDI file's track+channel pair, because that is the only reliable way to + separate instruments across the inconsistent MIDI files people upload. + */ + parts.push({ + id: `${track.index}:${channelInfo.channel}`, + trackIndex: track.index, + channel: channelInfo.channel, + label: visibleLabel, + sourceLabel: buildPartSourceLabel(track, channelInfo), + shortLabel: `${Number(track.index) + 1}.${Number(channelInfo.channel) + 1}`, + noteCount: notes.length, + minNote: channelInfo.minNote, + maxNote: channelInfo.maxNote, + averageNote: channelInfo.averageNote, + isPercussion: Boolean(channelInfo.isPercussion), + notes, + }); + }); + }); + + return parts.sort((a, b) => { + if (a.isPercussion !== b.isPercussion) return a.isPercussion ? 1 : -1; + return b.noteCount - a.noteCount || a.trackIndex - b.trackIndex || a.channel - b.channel; + }); +} + +export function getDefaultSelectedPartIds(parts = []) { + const playable = Array.isArray(parts) ? parts : []; + const pitchedParts = playable.filter((part) => !part.isPercussion); + const candidates = pitchedParts.length ? pitchedParts : playable; + + /* + Default to a small, useful ensemble instead of everything. Dense MIDI files + can overwhelm a one-note Roomba beeper, so selecting the largest pitched + parts gives the user a recognizable starting point while keeping drums off + unless the file has nothing else. + */ + return candidates.slice(0, 6).map((part) => part.id); +} + +export function getPresetPartIds(parts = [], preset = 'default') { + const playable = Array.isArray(parts) ? parts : []; + const pitchedParts = playable.filter((part) => !part.isPercussion); + const source = pitchedParts.length ? pitchedParts : playable; + + switch (preset) { + case 'none': + return []; + case 'all-pitched': + return source.map((part) => part.id); + case 'bass': { + const sorted = [...source].sort((a, b) => a.averageNote - b.averageNote || b.noteCount - a.noteCount); + return sorted.slice(0, 2).map((part) => part.id); + } + case 'melody': { + const sorted = [...source].sort((a, b) => b.averageNote - a.averageNote || b.noteCount - a.noteCount); + return sorted.slice(0, 3).map((part) => part.id); + } + default: + return getDefaultSelectedPartIds(playable); + } +} + +export function collectNotesForParts(parts = [], selectedPartIds = []) { + if (!Array.isArray(parts) || !Array.isArray(selectedPartIds) || selectedPartIds.length === 0) return []; + const selected = new Set(selectedPartIds.map((id) => String(id))); + return parts + .filter((part) => selected.has(String(part.id))) + .flatMap((part) => part.notes || []) + .sort((a, b) => a.startMs - b.startMs || b.velocity - a.velocity || b.noteNumber - a.noteNumber); +} + +function groupNotesByStart(notes = []) { + const groups = []; + let current = null; + + notes.forEach((note) => { + /* + A tiny tolerance catches chord notes that quantize to the same musical + time but differ by a fraction of a millisecond after tempo conversion. + */ + if (!current || Math.abs(note.startMs - current.startMs) > 1) { + current = { startMs: note.startMs, notes: [] }; + groups.push(current); + } + current.notes.push(note); + }); + + return groups; +} + +function noteDurationToRoombaTicks(note, fallbackTicks, maxTicks) { + const naturalTicks = note.durationMs / ROOMBA_DURATION_TICK_MS; + const cap = clampRoombaDurationTicks(maxTicks || MAX_FILE_NOTE_TICKS); + return clampRoombaDurationTicks(Math.min(cap, naturalTicks || fallbackTicks)); +} + +export function filterNotesByChannels(notes = [], selectedChannels = []) { + if (!Array.isArray(selectedChannels) || selectedChannels.length === 0) return []; + const channelSet = new Set(selectedChannels.map((channel) => Number(channel))); + return notes.filter((note) => channelSet.has(Number(note?.channel))); +} + +export function buildBeeperEvents(notes = [], mode = 'mono', options = {}) { + const groups = groupNotesByStart(notes); + const events = []; + const arpeggioTicks = clampRoombaDurationTicks(options.arpeggioTicks || DEFAULT_ARPEGGIO_NOTE_TICKS); + const arpeggioLimit = clamp(Math.round(options.arpeggioLimit || DEFAULT_ARPEGGIO_NOTE_LIMIT), 1, 16); + const monoFallbackTicks = clampRoombaDurationTicks(options.monoFallbackTicks || DEFAULT_FILE_NOTE_TICKS); + const monoMaxTicks = clampRoombaDurationTicks(options.monoMaxTicks || MAX_FILE_NOTE_TICKS); + + groups.forEach((group) => { + const playableNotes = [...group.notes].sort((a, b) => { + /* + Higher velocity usually represents the melody or accented chord tone. + Note number breaks ties so dense chords become predictable instead of + depending on the file's internal event order. + */ + return b.velocity - a.velocity || b.noteNumber - a.noteNumber; + }); + + if (mode === 'arpeggio') { + playableNotes.slice(0, arpeggioLimit).forEach((note, index) => { + const ticks = arpeggioTicks; + events.push({ + atMs: group.startMs + index * roombaTicksToMs(ticks), + note: clampRoombaNote(note.noteNumber), + duration: ticks, + }); + }); + return; + } + + const selected = playableNotes[0]; + if (!selected) return; + events.push({ + atMs: selected.startMs, + note: clampRoombaNote(selected.noteNumber), + duration: noteDurationToRoombaTicks(selected, monoFallbackTicks, monoMaxTicks), + }); + }); + + return events.sort((a, b) => a.atMs - b.atMs || b.note - a.note); +} + +function createChunk(startMs) { + return { + startMs, + notes: [], + durationMs: 0, + sourceEndMs: startMs, + }; +} + +export function buildRoombaSongChunks(events = []) { + const chunks = []; + const sortedEvents = [...events].sort((a, b) => a.atMs - b.atMs || b.note - a.note); + let chunk = null; + let cursorMs = 0; + + sortedEvents.forEach((event) => { + const noteDurationMs = roombaTicksToMs(event.duration); + const hasOpenChunk = Boolean(chunk && chunk.notes.length > 0); + const gapAfterCurrentChunk = hasOpenChunk ? event.atMs - cursorMs : 0; + const shouldStartNewChunk = + !hasOpenChunk || + chunk.notes.length >= ROOMBA_SONG_MAX_NOTES || + gapAfterCurrentChunk > FILE_CHUNK_GAP_THRESHOLD_MS; + + if (shouldStartNewChunk) { + /* + A new chunk is scheduled at the MIDI event time when there is real + silence before it. If the incoming event overlaps the previous phrase, + it starts at the current serialized cursor instead so playback bends + toward "play the next note" instead of "drop the next note". + */ + const startMs = Math.max(event.atMs, cursorMs); + chunk = createChunk(startMs); + chunks.push(chunk); + cursorMs = startMs; + } + + const safeNote = { + note: clampRoombaNote(event.note), + duration: clampRoombaDurationTicks(event.duration), + }; + + chunk.notes.push(safeNote); + chunk.durationMs += noteDurationMs; + chunk.sourceEndMs = chunk.startMs + chunk.durationMs; + cursorMs += noteDurationMs; + }); + + return chunks; +} + +export async function parseMidiFile(file) { + const bytes = new Uint8Array(await file.arrayBuffer()); + const parsed = parseMidi(bytes); + const ticksPerBeat = Number(parsed?.header?.ticksPerBeat || parsed?.header?.timeDivision || 0); + if (!ticksPerBeat || ticksPerBeat < 0) { + throw new Error('Only beat-based MIDI timing is supported.'); + } + + const tempoMap = createTempoMap(parsed); + const tracks = (parsed.tracks || []).map((track, index) => { + const extracted = extractTrackNotes(track, tempoMap, ticksPerBeat); + const channels = summarizeChannels(extracted.notes); + return { + index, + name: extracted.trackName, + label: formatTrackLabel(index, extracted.trackName, extracted.notes.length, channels), + notes: extracted.notes, + noteCount: extracted.notes.length, + channels, + }; + }); + const parts = buildPlayableParts(tracks); + + return { + fileName: file.name, + format: parsed.header?.format, + ticksPerBeat, + tracks, + parts, + }; +}