/** * This class is intended as a placeholder for utility methods unrelated * to actual classes of the game system or of FoundryVTT */ export class Misc { static isFunction(v) { return v && {}.toString.call(v) === '[object Function]'; } static upperFirst(text) { return text.charAt(0).toUpperCase() + text.slice(1); } static toSignedString(number) { const value = parseInt(number) const isPositiveNumber = value != NaN && value > 0; return isPositiveNumber ? "+" + number : number } static sum() { return (a, b) => a + b; } static ascending(orderFunction = x=>x) { return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b)); } static descending(orderFunction = x=>x) { return (a, b) => Misc.sortingBy(orderFunction(b), orderFunction(a)); } static sortingBy(a, b) { if (a > b) return 1; if (a < b) return -1; return 0; } /** * Converts the value to an integer, or to 0 if undefined/null/not representing integer * @param {*} value value to convert to an integer using parseInt */ static toInt(value) { if (value == undefined) { return 0; } const parsed = parseInt(value); return isNaN(parsed) ? 0 : parsed; } static keepDecimals(num, decimals) { if (decimals<=0 || decimals>6) return num; const decimal = Math.pow(10, parseInt(decimals)); return Math.round(num * decimal) / decimal; } static getFractionHtml(diviseur) { if (!diviseur || diviseur <= 1) return undefined; switch (diviseur || 1) { case 2: return '½'; case 4: return '¼'; default: return '1/' + diviseur; } } static classify(items, classifier = it => it.type, transform = it => it) { let itemsBy = {}; Misc.classifyInto(itemsBy, items, classifier, transform); return itemsBy; } static classifyFirst(items, classifier) { let itemsBy = {}; for (const item of items) { const classification = classifier(item); if (!itemsBy[classification]) { itemsBy[classification] = item; } } return itemsBy; } static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) { for (const item of items) { const classification = classifier(item); let list = itemsBy[classification]; if (!list) { list = []; itemsBy[classification] = list; } list.push(transform(item)); } for (const [key, list] of Object.entries(itemsBy)) { list.sort(); }; } static rollOneOf(array) { return array[new Roll("1d" + array.length).evaluate({ async: false }).total - 1]; } static distinct(array) { return [...new Set(array)]; } static data(it) { if (it instanceof Actor || it instanceof Item || it instanceof Combatant) { return it.data; } return it; } static templateData(it) { return Misc.data(it)?.data ?? {} } static connectedGM() { return game.users.entities.find(u => u.isGM && u.active)?.id; } }