import { ACTOR_IMAGES, ITEM_IMAGES, LESOUBLIES_CONFIG, PROFILE_KEYS } from "./les-oublies-config.js" export class LesOubliesUtility { static registerHandlebarsHelpers() { Handlebars.registerHelper("eq", (left, right) => left === right) Handlebars.registerHelper("join", (values, separator = ", ") => Array.isArray(values) ? values.filter(Boolean).join(separator) : "") Handlebars.registerHelper("count", (values) => Array.isArray(values) ? values.length : 0) Handlebars.registerHelper("concat", (...parts) => parts.slice(0, -1).join("")) Handlebars.registerHelper("profileLabel", (key) => LESOUBLIES_CONFIG.profileLabels[key] ?? key) Handlebars.registerHelper("skillLabel", (key) => LESOUBLIES_CONFIG.skills[key]?.label ?? key) Handlebars.registerHelper("formatPrice", (value) => Number(value) > 0 ? `${value} e` : "—") Handlebars.registerHelper("formatSkillBonus", (bonus) => { const keys = [bonus.key, ...(bonus.alternativeKeys ?? [])] .filter(Boolean) .map((key) => LESOUBLIES_CONFIG.skills[key]?.label ?? key) const label = keys.join(" ou ") const domains = [] if (Array.isArray(bonus.domainsGranted) && bonus.domainsGranted.length) domains.push(bonus.domainsGranted.join(", ")) if (Number(bonus.domainsToChoose ?? 0) > 0) { const prefix = bonus.domainsToChoose > 1 ? `${bonus.domainsToChoose} choix` : "1 choix" domains.push(bonus.domainsChoiceText ? `${prefix} : ${bonus.domainsChoiceText}` : prefix) } return domains.length ? `${label} +${bonus.base} — ${domains.join(" ; ")}` : `${label} +${bonus.base}` }) Handlebars.registerHelper("formatEquipmentEntry", (entry) => { const baseLabel = entry.choiceText || entry.name || "" const quantity = Number(entry.quantity ?? 0) > 1 ? ` x${entry.quantity}` : "" const extras = [] if (entry.details) extras.push(entry.details) if (Number(entry.ecorces ?? 0) > 0) extras.push(`${entry.ecorces} écorces`) return extras.length ? `${baseLabel}${quantity} — ${extras.join(", ")}` : `${baseLabel}${quantity}` }) Handlebars.registerHelper("formatSpellGrant", (grant) => { const discipline = LESOUBLIES_CONFIG.skills[grant.skillKey]?.label ?? grant.skillKey ?? grant.tradition return `${grant.tradition} (${discipline}) / ${grant.polarity} : ${grant.amount}` }) } static getDefaultActorImage(type) { return ACTOR_IMAGES[type] ?? "icons/svg/mystery-man.svg" } static getDefaultItemImage(type) { return ITEM_IMAGES[type] ?? "icons/svg/item-bag.svg" } static createChoices(values = [], labels = {}) { return values.map((value) => ({ value, label: labels[value] ?? String(value), })) } static createRangeChoices(min, max, labels = {}) { return Array.from({ length: Math.max(max - min + 1, 0) }, (_, index) => min + index).map((value) => ({ value, label: labels[value] ?? String(value), })) } static ensureChoice(choices = [], value, label = null) { if (value === undefined || value === null || value === "") return choices if (choices.some((choice) => String(choice.value) === String(value))) return choices return [{ value, label: label ?? `${value} (personnalisé)`, }, ...choices] } static createEmptyProfiles() { return PROFILE_KEYS.reduce((profiles, key) => { profiles[key] = 0 return profiles }, {}) } static computeDreamPointTotals(songesValue, cauchemarValue) { if (songesValue > cauchemarValue) { return { songesPoints: songesValue * 2 - cauchemarValue, cauchemarPoints: cauchemarValue, } } if (songesValue === cauchemarValue) { return { songesPoints: songesValue, cauchemarPoints: cauchemarValue, } } return { songesPoints: songesValue, cauchemarPoints: cauchemarValue * 3 - songesValue * 2, } } static sortByName(documents = []) { return [...documents].sort((left, right) => left.name.localeCompare(right.name, "fr")) } static uniqueStrings(values = []) { return [...new Set((Array.isArray(values) ? values : []) .map((value) => String(value ?? "").trim()) .filter(Boolean))] } static async prepareEnrichedHtml(documentName, type, systemData) { const htmlFields = game.system.documentTypes?.[documentName]?.[type]?.htmlFields ?? [] const enriched = {} for (const path of htmlFields) { const value = foundry.utils.getProperty(systemData, path) ?? "" const html = await foundry.applications.ux.TextEditor.implementation.enrichHTML(value, { async: true }) foundry.utils.setProperty(enriched, path, html) } return enriched } }