UNPKG

sus-io

Version:

A SUS (Sliding Universal Score) converter (parser and stringifier).

3 lines (2 loc) 6.95 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["sus-io"]={})}(this,(function(e){"use strict";function t(e){return e.replace(/^"(.*(?="$))"$/,"$1")}function r(e){const t=[];let r;for(const s of e.sort(((e,t)=>e.tick-t.tick)))r||(r=[],t.push(r)),r.push(s),2===s.type&&(r=void 0);return t}function s(e,t){const[r]=e,s=Number.parseInt(r[4],36);return n(e,t).map((([e,t])=>{const r=Number.parseInt(t[1],36);return{tick:e,lane:s,width:r,type:Number.parseInt(t[0],36)}}))}function n([e,t],r){const s=+e.substring(0,3);return(t.match(/.{2}/g)||[]).map(((e,t,n)=>"00"!==e&&[r(s,t,n.length),e])).filter((e=>!!e))}function a(e){var a,o;const i=function(e){const r=[],s=[];for(const n of e.split(/\r\n|(?!\r\n)[\n-\r\x85\u2028\u2029]/)){if(!n.startsWith("#"))continue;const e=n.match(/^#([^:]+): *(.*)$/);if(e){const[s,n]=e.slice(1);r.push([s,t(n)]);continue}const a=n.match(/^#(.+?) (.*)$/);if(a){const[e,r]=a.slice(1);s.push([e,t(r)])}else console.warn(`Unknown SUS data line: "${n}"`)}return{score:r,metadata:s}}(e),c=function(e){const t={};for(const[r,s]of e)switch(r){case"TITLE":t.title=s;break;case"SUBTITLE":t.subtitle=s;break;case"ARTIST":t.artist=s;break;case"GENRE":t.genre=s;break;case"DESIGNER":t.designer=s;break;case"DIFFICULTY":t.difficulty=s;break;case"PLAYLEVEL":t.playlevel=s;break;case"SONGID":t.songid=s;break;case"WAVE":t.wave=s;break;case"JACKET":t.jacket=s;break;case"BACKGROUND":t.background=s;break;case"MOVIE":t.movie=s;break;case"WAVEOFFSET":t.waveoffset=Number.parseInt(s);break;case"MOVIEOFFSET":t.movieoffset=Number.parseInt(s);break;case"BASEBPM":t.basebpm=Number.parseInt(s);break;case"REQUEST":{const e=t.requests||[];e.push(s),t.requests=e;break}default:console.log("Unknown metadata header: ",r)}return t}(i.metadata),u=null===(a=c.requests)||void 0===a?void 0:a.find((e=>e.startsWith("ticks_per_beat")));u||console.warn("Missing ticks_per_beat request, defaulting to 480.");const l=Number.parseInt(null!==(o=null==u?void 0:u.split(" ")[1])&&void 0!==o?o:"")||480;return Object.assign({metadata:c},function(e,t){var a;const o=e.filter((([e])=>5===e.length&&e.endsWith("02")&&!Number.isNaN(Number.parseInt(e)))).map((([e,t])=>[Number.parseInt(e.substring(0,3)),Number.parseInt(t)]));0===o.length&&(console.warn("No barLengths found, adding default 4/4 time signature (#00002:4)..."),o.push([0,4]));let i=0;const c=[...o].sort((([e],[t])=>e-t)).map((([e,r],s,n)=>{const a=n[s-1];return a&&(i+=(e-a[0])*a[1]*t),{measure:e,ticksPerMeasure:r*t,ticks:i}})).reverse(),u=(e,t,r)=>{const s=c.find((t=>e>=t.measure));if(!s)throw"Unexpected missing bar";return s.ticks+(e-s.measure)*s.ticksPerMeasure+t*s.ticksPerMeasure/r},l=new Map,f=[],p=[],h=[],d=new Map;for(const t of e){const[e,r]=t;if(5===e.length&&e.startsWith("BPM"))l.set(e.substring(3),+r);else if(5===e.length&&e.endsWith("08"))f.push(...n(t,u));else if(5!==e.length||"1"!==e[3])if(6!==e.length||"3"!==e[3])5===e.length&&"5"===e[3]&&h.push(...s(t,u));else{const r=e[5],n=null!==(a=d.get(r))&&void 0!==a?a:[];n.push(...s(t,u)),d.set(r,n)}else p.push(...s(t,u))}return{taps:p,directionals:h,slides:[...d.values()].flatMap(r),bpms:f.sort(((e,t)=>e[0]-t[0])).map((([e,t])=>[e,l.get(t)||0])).reverse(),barLengths:o}}(i.score,l))}"function"==typeof SuppressedError&&SuppressedError;class o extends Error{constructor(e,t){super(`Notes are not aligned correctly, with gcd ${e}. Note ticks: ${t.join(", ")}`),this.name="InvalidAlignmentError",this.gcdValue=e,this.noteTicks=t}}var i;function c(e,t){return e<t?c(t,e):0===t?e:c(t,e%t)}class u extends Map{constructor(e){super(),this.generateDefault=e}get(e){const t=super.get(e);if(void 0===t){const t=this.generateDefault();return super.set(e,t),t}return t}}class l{constructor(){i.set(this,void 0),function(e,t,r,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");"a"===s?n.call(e,r):n?n.value=r:t.set(e,r)}(this,i,[...Array(36).keys()].map((e=>[e,[0,0]])),"f")}generateChannel(e,t){const r=function(e,t,r,s){if("a"===r&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!s:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(e):s?s.value:t.get(e)}(this,i,"f").find((([,[r,s]])=>0===r&&0===s||t<r||s<e));if(!r)throw new Error("No more channel available.");return r[1]=[e,t],r[0]}}function f(e,t="This file was generated by sus-js v1.1.0"){var r;const{metadata:s,bpms:n,taps:a,directionals:i,slides:f,barLengths:p}=e;let h=480;const d=[];d.push(t);for(const[e,t]of Object.entries(s))if("requests"!==e)d.push(`#${e.toUpperCase()} ${"number"==typeof t?t:(g=t,`"${g}"`)}`);else{d.push("");for(const e of t)d.push(`#REQUEST "${e}"`),e.startsWith("ticks_per_beat")&&(h=+e.split(" ")[1])}var g;d.push("");const b=new u((()=>({raws:[],ticksPerMeasure:0})));for(const[e,t]of p)d.push(`#${e.toString().padStart(3,"0")}02:${t}`);d.push("");let m=0;const k=p.map((([e,t],r,s)=>{var n;const[a]=null!==(n=s[r+1])&&void 0!==n?n:[Number.POSITIVE_INFINITY],o=m;return m+=(a-e)*t*h,{tick:o,measure:e,value:t}})).reverse(),w=(e,t,r)=>{var s;const{tick:n,measure:a,value:o}=null!==(s=k.find((({tick:t})=>e>=t)))&&void 0!==s?s:{tick:0,measure:0,value:4},i=Math.floor(a+(e-n)/h/o),c=b.get(`${i.toString().padStart(3,"0")}${t}`);c.raws.push({tick:e-n,value:r}),c.ticksPerMeasure=o*h};if(n.length>=Math.pow(36,2)-1)throw new Error(`Too much BPMS (${n.length} >= 36^2 -1 = ${Math.pow(36,2)-1})`);const v=new Map;for(const[e,t]of n){const s=(v.size+1).toString(36).padStart(2,"0");v.has(t)||(v.set(t,s),d.push(`#BPM${v.get(t)}:${t}`)),w(e,"08",null!==(r=v.get(t))&&void 0!==r?r:s)}for(const{tick:e,lane:t,width:r,type:s}of a)w(e,`1${t.toString(36)}`,`${s}${r.toString(36)}`);for(const{tick:e,lane:t,width:r,type:s}of i)w(e,`5${t.toString(36)}`,`${s}${r.toString(36)}`);const E=new l;for(const e of f){const t=e[0].tick,r=e[e.length-1].tick,s=E.generateChannel(t,r).toString(36);for(const{tick:t,lane:r,width:n,type:a}of e)w(t,`3${r.toString(36)}${s}`,`${a}${n.toString(36)}`)}return b.forEach((({raws:e,ticksPerMeasure:t},r)=>{var s;const n=e.reduce(((e,t)=>c(t.tick,e)),t);if(!Number.isInteger(n))throw new o(n,e.map((({tick:e})=>e)));const a=new Map(e.sort((({tick:e},{tick:t})=>e-t)).map((({tick:e,value:r})=>[e%t,r]))),i=[];for(let e=0;e*n<t;e++){const t=e*n;i.push(null!==(s=a.get(t))&&void 0!==s?s:"00")}d.push(`#${r}:${i.join("")}`)})),d.join("\n")}i=new WeakMap;var p={parse:a,stringify:f};e.default=p,e.parse=a,e.stringify=f,Object.defineProperty(e,"__esModule",{value:!0})})); //# sourceMappingURL=index.umd.js.map