diff --git a/module/settings/meta.mjs b/module/settings/meta.mjs index 78f6ad1..83ea057 100644 --- a/module/settings/meta.mjs +++ b/module/settings/meta.mjs @@ -1,9 +1,34 @@ +function createDiceTable(size) { + return { + name: `Dice/d${size}`, + buckets: { + type: `range`, + min: 1, + max: size, + step: 1, + }, + graph: { + type: `bar`, + stacked: true, + }, + }; +}; + export function registerMetaSettings() { game.settings.register(__ID__, `tables`, { scope: `world`, - type: Array, + type: Object, config: false, requiresReload: false, + default: { + "Dice/d4": createDiceTable(4), + "Dice/d6": createDiceTable(6), + "Dice/d8": createDiceTable(8), + "Dice/d10": createDiceTable(10), + "Dice/d12": createDiceTable(12), + "Dice/d20": createDiceTable(20), + "Dice/d100": createDiceTable(100), + }, }); game.settings.register(__ID__, `data`, { diff --git a/module/utils/databases/Database.mjs b/module/utils/databases/Database.mjs new file mode 100644 index 0000000..e9400d7 --- /dev/null +++ b/module/utils/databases/Database.mjs @@ -0,0 +1,89 @@ +/* eslint-disable no-unused-vars */ + +export class Database { + // MARK: Table Ops + static createTable(tableConfig) { + throw new Error(`createTable() must be defined`); + }; + + /** @returns {Array} */ + static getTables() { + const tables = game.settings.get(__ID__, `tables`); + return Object.values(tables) ?? []; + }; + + static getTable(tableID) { + const tables = game.settings.get(__ID__, `tables`); + if (!tables[tableID]) { return }; + return tables[tableID]; + }; + + static deleteTable(tableID) { + throw new Error(`deleteTable() must be defined`); + }; + + // MARK: Row Ops + static createRow(table, userID, row) { + throw new Error(`createRow() must be implemented`); + }; + + static getRows(tableID, userIDs, privacy = `none`) { + throw new Error(`getRows() must be implemented`); + }; + + static updateRow(table, userID, rowID, changes) { + throw new Error(`updateRow() must be implemented`); + }; + + static deleteRow(table, userID, rowID) { + throw new Error(`deleteRow() must be implemented`); + }; + + // MARK: Applications + static _apps = new Map(); + + /** + * Adds an application into the registry so that when a data update + * is received, we can re-render the sheets. + * + * @param app an ApplicationV2 instance + */ + static addApp(app) { + this._apps.set(app.id, app); + this.registerListeners(); + }; + + /** + * Adds an application into the registry so that when a data update + * is received, we can re-render the sheets. + * + * @param app an ApplicationV2 instance + */ + static removeApp(app) { + this._apps.delete(app.id); + if (this._apps.size === 0) { + this.unregisterListeners(); + }; + }; + + /** + * Rerenders all of the applications that are displaying data from + * this database + */ + static render() { + for (const app of Object.values(this.apps)) { + app.render(); + }; + }; + + // MARK: Listeners + /** + * Used to listen for changes from other clients and rerender the apps + * as required in order to keep the data as up-to-date as possible. + */ + static registerListeners() {}; + + static unregisterListeners() {}; +}; + +/* eslint-enable no-unused-vars */ diff --git a/module/utils/databases/Memory.mjs b/module/utils/databases/Memory.mjs index 70af985..f3698ae 100644 --- a/module/utils/databases/Memory.mjs +++ b/module/utils/databases/Memory.mjs @@ -1,9 +1,9 @@ -/* eslint-disable no-unused-vars */ +import { Database } from "./Database.mjs"; import { filterPrivateRows } from "../filterPrivateRows.mjs"; const { randomID, mergeObject } = foundry.utils; -export class MemoryDatabase { +export class MemoryDatabase extends Database { static #tables = { "Dice/d10": { name: `Dice/d10`, @@ -14,7 +14,8 @@ export class MemoryDatabase { max: 10, step: 1, }, - config: { + graph: { + type: `bar`, stacked: true, }, }, @@ -74,8 +75,8 @@ export class MemoryDatabase { static #rows = {}; + /** @returns {Array
} */ static getTables() { - /** @type {Array<{ name: string; }>} */ return Object.values(this.#tables); }; @@ -146,5 +147,3 @@ export class MemoryDatabase { static unregisterListeners() {}; }; - -/* eslint-enable no-unused-vars */ diff --git a/module/utils/validateValue.mjs b/module/utils/validateValue.mjs index d141083..4440d96 100644 --- a/module/utils/validateValue.mjs +++ b/module/utils/validateValue.mjs @@ -3,7 +3,13 @@ import { Logger } from "./Logger.mjs"; const { deepClone } = foundry.utils; const { StringField, NumberField } = foundry.data.fields; +/** + * @param {unknown} value The value to validate + * @param {BucketConfig} options The bucket config for the table + * @returns Whether or not the value is valid for the table + */ export function validateValue(value, options) { + /** @type {BucketConfig} */ let opts = deepClone(options); if (validatorTypes[opts.type] == null) { Logger.error(`Failed to find type validator for: ${opts.type}`);