UNPKG

tiny-essentials

Version:

Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.

1 lines 4.6 kB
(()=>{"use strict";var e={d:(r,t)=>{for(var o in t)e.o(t,o)&&!e.o(r,o)&&Object.defineProperty(r,o,{enumerable:!0,get:t[o]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)},r={};function t(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)&&"[object Object]"===Object.prototype.toString.call(e)}e.d(r,{TinySimpleDice:()=>n});class o{static _safeEvaluate(e){if(!/^[\d+\-*/%.()\s^]+$/.test(e))throw new Error(`Invalid characters in expression: "${e}"`);const r=e.replace(/\^/g,"**");try{return Function(`"use strict"; return (${r})`)()}catch(r){if(!(r instanceof Error))throw new Error("Unknown Error");throw new Error(`Invalid expression "${e}": ${r.message}`)}}static replaceValues(e,r){let t=0;return e.replace(/(\d*)d(\d+)/g,(e,o)=>{const n=o?Number(o):1;let s=0;for(let e=0;e<n;e++){const e=r[t++];s+=void 0!==e?e:0}return String(s)})}static tokenizeValues(e,r){const t=o.replaceValues(e,r),n=[],s=/\d+|[()+\-*/]/g;let a;for(;null!==(a=s.exec(t));)/^\d+$/.test(a[0])?n.push(Number(a[0])):n.push(a[0]);return{tokens:n,text:t}}static parseString(e){if("string"!=typeof e)throw new TypeError("Input must be a string.");const r=e.split(",").map(e=>e.trim()).filter(Boolean),t=[],o=[];if(r.forEach((e,r)=>{const n=/\b(?:(\d+)?d(\d+))\b/g;let s;const a=[],i=e.replace(/\(([^()]+?\|[^()]+?)\)/g,(e,r)=>{const t="string"==typeof r?r.split("|").map(e=>e.trim()).filter(Boolean):[];if(0===t.length)throw new Error(`Invalid random-choice group: "${e}"`);return t[Math.floor(Math.random()*t.length)]});for(;null!==(s=n.exec(i));){const e=parseInt(s[1]||"1",10),t=parseInt(s[2],10);if(isNaN(t))throw new Error(`Invalid dice sides in expression "${s[0]}" at position ${r+1}.`);a.push({count:e,sides:t})}if(0===a.length&&Number.isNaN(parseFloat(i)))throw new Error(`Invalid dice expression at position ${r+1}: "${e}"`);t.push(...a),o.push({index:r,original:e,expression:i})}),0===t.length)throw new Error("Invalid dice amount.");return{sides:t,modifiers:o}}static applyModifiers(e,r){if(!Array.isArray(e)||!e.every(e=>"number"==typeof e&&!Number.isNaN(e)||t(e)&&"number"==typeof e.value&&!Number.isNaN(e.value)&&"number"==typeof e.sides&&!Number.isNaN(e.sides)))throw new TypeError("Bases must be a valid numbers.");if(!Array.isArray(r))throw new TypeError("Modifiers must be an array of modifier objects.");let n=0;const s=[],a=[...e];for(const e in r){const i=r[e];if("string"!=typeof i.expression)throw new Error("Each modifier must include an expression string.");const l=i.original,u=i.expression,c=[],p=[],f=[],h=e=>e.match(/\(\s*[^()]+\|\s*[^()]+\s*\)|\b\d*d\d+\b|[-+]?\d+(?:\.\d+)?|[+\-*/%^()]/g)||[],d=h(u),m=h(l),w=[...d],b=[],y=u.replace(/\b\d*d\d+\b/g,e=>{const r=e.split("d"),o=()=>{for(const r in d)if(d[r]===e&&b.indexOf(r)<0){b.push(r),f.push(Number(r));break}},n=e=>{if(e.value>e.sides)throw new Error(`Invalid dice roll: value (${e.value}) must be between 1 and ${e.sides}.`)};if(0===r[0].trim().length){const r=a.shift(),s="number"==typeof r?r:t(r)?r.value:0;t(r)&&n(r),c.push([s]);for(const r in w)if(w[r]===e){w[r]=String(s),p.push(Number(r));break}return o(),s}const s=[],i=Number(r[0]),l=["("];let u="(";for(let e=0;e<i;e++){const r=a.shift(),o="number"==typeof r?r:t(r)?r.value:0;t(r)&&n(r),l.push(String(o));const c=e<i-1?" + ":")";l.push(c),u+=`${o}${c}`,s.push(o)}for(const r in w){const t=Number(r);if(w[t]===e){w.splice(t,1,...l);let e=1;for(let r=0;r<i;r++)p.push(t+r+e),e++;break}}return c.push(s),o(),u});let g;try{g=o._safeEvaluate(y)}catch(e){if(!(e instanceof Error))throw new Error("Unknown Error");throw new Error(`Error evaluating expression "${y}" (from "${u}"): ${e.message}`)}s.push({rawTokensP:d,rawTokens:m,tokens:w,rawDiceTokenSlots:f,diceTokenSlots:p,dicesResult:c,total:g}),n+=g}return{final:n,steps:s}}static rollArrayIndex(e){const r=Array.isArray(e),t=e instanceof Set;if(!r&&!t)throw new TypeError("rollArrayIndex expects an array or Set.");return Math.floor(Math.random()*(r?e.length:e.size))}#e;#r;get maxValue(){return this.#e}set maxValue(e){if(!Number.isInteger(e)||e<0)throw new TypeError("maxValue must be an integer greater than -1.");this.#e=e}get allowZero(){return this.#r}set allowZero(e){if("boolean"!=typeof e)throw new TypeError("allowZero must be a boolean.");this.#r=e}constructor({maxValue:e,allowZero:r=!0}){if("boolean"!=typeof r)throw new TypeError("allowZero must be an boolean.");if(!Number.isInteger(e)||e<0)throw new TypeError("maxValue must be an integer greater than -1.");this.#e=e,this.#r=r}roll(){const e=this.#r?0:1;return Math.floor(Math.random()*(this.#e-e+1))+e}}const n=o;window.TinySimpleDice=r.TinySimpleDice})();