From aa5285df214913a99f45ab23484ace9e298d82f9 Mon Sep 17 00:00:00 2001 From: akrigline Date: Thu, 23 Mar 2023 18:13:47 -0400 Subject: [PATCH 1/2] feat: create a duration data model --- system/CONSTANTS.mjs | 13 +--- system/datamodels/item/common/duration.mjs | 34 +++++++++ system/helpers/HELPERS.mjs | 9 +++ system/helpers/debug.mjs | 9 +++ system/helpers/roundHelpers.mjs | 87 ++++++++++++++++++++++ 5 files changed, 142 insertions(+), 10 deletions(-) create mode 100644 system/datamodels/item/common/duration.mjs create mode 100644 system/helpers/HELPERS.mjs create mode 100644 system/helpers/debug.mjs create mode 100644 system/helpers/roundHelpers.mjs diff --git a/system/CONSTANTS.mjs b/system/CONSTANTS.mjs index b34acb2..d839d23 100644 --- a/system/CONSTANTS.mjs +++ b/system/CONSTANTS.mjs @@ -1,14 +1,8 @@ +import { HELPERS } from "./helpers/HELPERS.mjs"; + export const SYSTEM_ID = "black-flag"; export const SYSTEM_NAME = "Black Flag 🏴"; -function isDebugging() { - return game.modules.get("_dev-mode")?.api?.getPackageDebugValue(SYSTEM_ID); -} - -function log(...args) { - if ( isDebugging() ) console.log(`${SYSTEM_NAME} |`, ...args); -} - /** * The expected distance units. * @type {{label: string}} @@ -252,10 +246,9 @@ const CHARACTER_BUILDER_MODES = { * @type {Object} */ export const SYSTEM = { + ...HELPERS, id: SYSTEM_ID, name: SYSTEM_NAME, - log, - isDebugging, TOOL_TYPES, SKILL_TYPES, PROFICIENCY_TYPES, diff --git a/system/datamodels/item/common/duration.mjs b/system/datamodels/item/common/duration.mjs new file mode 100644 index 0000000..4dc8e17 --- /dev/null +++ b/system/datamodels/item/common/duration.mjs @@ -0,0 +1,34 @@ +/** + * Data model template for a Duration, as may be used by Powers + * + * @property {string} type + * @mixin + */ +export default class DurationDataModel extends foundry.abstract.DataModel { + + /** @inheritdoc */ + static _enableV10Validation = true; + + /** @inheritDoc */ + static defineSchema() { + const fields = foundry.data.fields; + return { + type: new fields.StringField({ + required: true, + choices: ["instantaneous", "time", "permanent", "special"], + initial: "instantaneous" + }), + + // Store duration internally as rounds, translating into human readable on the fly + rounds: new fields.NumberField({ + required: false + }), + + // Describes when during a round an effect might end + // e.g. "end of target's turn" or "end of caster's turn" + special: new fields.StringField({ + required: false + }) + }; + } +} diff --git a/system/helpers/HELPERS.mjs b/system/helpers/HELPERS.mjs new file mode 100644 index 0000000..75133d8 --- /dev/null +++ b/system/helpers/HELPERS.mjs @@ -0,0 +1,9 @@ +import {isDebugging, log} from "./debug.mjs"; +import {convertToRounds, formatRounds} from "./roundHelpers.mjs"; + +export const HELPERS = { + convertToRounds, + formatRounds, + isDebugging, + log +}; diff --git a/system/helpers/debug.mjs b/system/helpers/debug.mjs new file mode 100644 index 0000000..148dc4e --- /dev/null +++ b/system/helpers/debug.mjs @@ -0,0 +1,9 @@ + +export function isDebugging() { + return game.modules.get("_dev-mode")?.api?.getPackageDebugValue(SYSTEM_ID); +} + +export function log(...args) { + if ( isDebugging() ) console.log(`${SYSTEM_NAME} |`, ...args); +} + diff --git a/system/helpers/roundHelpers.mjs b/system/helpers/roundHelpers.mjs new file mode 100644 index 0000000..83b84d5 --- /dev/null +++ b/system/helpers/roundHelpers.mjs @@ -0,0 +1,87 @@ +/** + * Formats rounds for human readable display + * + * 1 round is nominally a "turn" + * 10 rounds is a minute + * 600 rounds is an hour + * 14400 rounds is a day + * 1008000 is a week + * 4032000 is a month + * 48384000 is a year + * + * @param {number} rounds + * @returns {{number: number, unit: string}} + */ +export function formatRounds(rounds) { + if (rounds < 10) { + return { + number: rounds, + unit: "turns" + }; + } + + if (rounds < 600) { + return { + number: Math.floor(rounds / 10), + unit: "minutes" + }; + } + + if (rounds < 14400) { + return { + number: Math.floor(rounds / 600), + unit: "hours" + }; + } + + if (rounds < 1008000) { + return { + number: Math.floor(rounds / 14400), + unit: "days" + }; + } + + if (rounds < 4032000) { + return { + number: Math.floor(rounds / 1008000), + unit: "weeks" + }; + } + + if (rounds < 48384000) { + return { + number: Math.floor(rounds / 4032000), + unit: "months" + }; + } + + return { + number: Math.floor(rounds / 48384000), + unit: "years" + }; +} + +/** + * Converts an object of number and unit into a number of rounds + * @param {number} number + * @param {string} unit + * @returns {number} - a number of rounds + */ +export function convertToRounds(number, unit) { + switch (unit) { + case "turns": + return number; + case "minutes": + return number * 10; + case "hours": + return number * 600; + case "days": + return number * 14400; + case "weeks": + return number * 1008000; + case "months": + return number * 4032000; + case "years": + return number * 48384000; + } +} From 5d7d802b510b2a1ed29a143d6a3bdc7bfa6fd1aa Mon Sep 17 00:00:00 2001 From: akrigline Date: Thu, 23 Mar 2023 18:22:13 -0400 Subject: [PATCH 2/2] refactor: alpha sort keys --- system/datamodels/item/common/duration.mjs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system/datamodels/item/common/duration.mjs b/system/datamodels/item/common/duration.mjs index 4dc8e17..ff8a3cc 100644 --- a/system/datamodels/item/common/duration.mjs +++ b/system/datamodels/item/common/duration.mjs @@ -13,12 +13,6 @@ export default class DurationDataModel extends foundry.abstract.DataModel { static defineSchema() { const fields = foundry.data.fields; return { - type: new fields.StringField({ - required: true, - choices: ["instantaneous", "time", "permanent", "special"], - initial: "instantaneous" - }), - // Store duration internally as rounds, translating into human readable on the fly rounds: new fields.NumberField({ required: false @@ -28,6 +22,12 @@ export default class DurationDataModel extends foundry.abstract.DataModel { // e.g. "end of target's turn" or "end of caster's turn" special: new fields.StringField({ required: false + }), + + type: new fields.StringField({ + required: true, + choices: ["instantaneous", "time", "permanent", "special"], + initial: "instantaneous" }) }; }