diff --git a/module/Apps/StatsViewer.mjs b/module/Apps/StatsViewer.mjs index 92c9b72..0850b2b 100644 --- a/module/Apps/StatsViewer.mjs +++ b/module/Apps/StatsViewer.mjs @@ -1,4 +1,5 @@ import { Chart } from "chart.js"; +import { diceSizeSorter } from "../utils/sorters/diceSize.mjs"; import { filePath } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; import { smallToLarge } from "../utils/sorters/smallToLarge.mjs"; @@ -36,7 +37,7 @@ export class StatsViewer extends HandlebarsApplicationMixin(ApplicationV2) { static PARTS = { tableSelect: { - template: filePath(`templates/Apps/StatsViewer/tableSelect.hbs`), + template: filePath(`templates/Apps/common/tableSelect.hbs`), }, dataFilters: { template: filePath(`templates/Apps/StatsViewer/dataFilters.hbs`), @@ -138,6 +139,14 @@ export class StatsViewer extends HandlebarsApplicationMixin(ApplicationV2) { ctx.tables = tableList; const subtableList = subtables[this._selectedTable]; + + // Sort the subtables to be sane + if (this._selectedTable === `Dice`) { + subtableList?.sort(diceSizeSorter); + } else { + subtableList?.sort(smallToLarge); + } + if (!subtableList) { this._selectedSubtable = undefined; } else if (!subtableList.includes(this._selectedSubtable)) { diff --git a/module/Apps/TableCreator.mjs b/module/Apps/TableCreator.mjs index ba55600..34271d7 100644 --- a/module/Apps/TableCreator.mjs +++ b/module/Apps/TableCreator.mjs @@ -1,4 +1,5 @@ import { BucketTypes } from "../utils/validateValue.mjs"; +import { createDiceTable } from "../utils/databases/utils.mjs"; import { filePath } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; @@ -20,7 +21,7 @@ export class TableCreator extends HandlebarsApplicationMixin(ApplicationV2) { }, position: { width: 320, - height: 206, + height: `auto`, }, actions: { createTable: this.#createTable, @@ -52,9 +53,12 @@ export class TableCreator extends HandlebarsApplicationMixin(ApplicationV2) { }; }; + /** @type {string} */ _name = ``; + /** @type {string} */ _type = BucketTypes.NUMBER; - async _preparePartContext(partId) { + #diceNamespaceAlert = null; + async _preparePartContext() { const ctx = {}; ctx.meta = { idp: this.id, @@ -62,8 +66,21 @@ export class TableCreator extends HandlebarsApplicationMixin(ApplicationV2) { ctx.name = this._name; ctx.type = this._type; + ctx.typeDisabled = false; ctx.types = Object.values(BucketTypes); + // Special Case for the dice namespace + if (this._name.startsWith(`Dice`)) { + ctx.typeDisabled = true; + ctx.type = BucketTypes.RANGE; + this.#diceNamespaceAlert = ui.notifications.info( + `Tables in the "Dice" namespace must be formatted as "Dice/dX" where X is the number of sides on the die and are restricted to be ranges 1 to X.`, + { permanent: true }, + ); + } else if (this.#diceNamespaceAlert != null) { + ui.notifications.remove(this.#diceNamespaceAlert); + }; + if (import.meta.env.DEV) { Logger.log(`Context`, ctx); }; @@ -89,8 +106,25 @@ export class TableCreator extends HandlebarsApplicationMixin(ApplicationV2) { }; static async #createTable() { - if (this._name === ``) { + /** @type {string} */ + const name = this._name; + if (name === ``) { ui.notifications.error(`Cannot create a table without a name`); }; + + const existing = CONFIG.StatsDatabase.getTable(name); + if (existing) { + ui.notifications.error(`A table with the name "${name}" already exists`); + }; + + if (name.startsWith(`Dice`)) { + if (!name.match(/^Dice\/d[0-9]+$/)) { + ui.notifications.error(`Table name doesn't conform to the "Dice/dX" format required by the Dice namespace.`); + return; + }; + const size = Number(name.replace(`Dice/d`, ``)); + CONFIG.StatsDatabase.createTable(createDiceTable(size)); + return; + }; }; }; diff --git a/module/settings/meta.mjs b/module/settings/meta.mjs index 83ea057..c236f7e 100644 --- a/module/settings/meta.mjs +++ b/module/settings/meta.mjs @@ -1,18 +1,4 @@ -function createDiceTable(size) { - return { - name: `Dice/d${size}`, - buckets: { - type: `range`, - min: 1, - max: size, - step: 1, - }, - graph: { - type: `bar`, - stacked: true, - }, - }; -}; +import { createDiceTable } from "../utils/databases/utils.mjs"; export function registerMetaSettings() { game.settings.register(__ID__, `tables`, { diff --git a/module/utils/databases/Memory.mjs b/module/utils/databases/Memory.mjs index df787b3..d45b607 100644 --- a/module/utils/databases/Memory.mjs +++ b/module/utils/databases/Memory.mjs @@ -74,6 +74,10 @@ export class MemoryDatabase extends Database { static #rows = {}; + static createTable(tableConfig) { + this.#tables[tableConfig.name] = tableConfig; + }; + /** @returns {Array} */ static getTables() { return Object.values(this.#tables); diff --git a/module/utils/databases/utils.mjs b/module/utils/databases/utils.mjs new file mode 100644 index 0000000..ba4cf69 --- /dev/null +++ b/module/utils/databases/utils.mjs @@ -0,0 +1,15 @@ +export function createDiceTable(size) { + return { + name: `Dice/d${size}`, + buckets: { + type: `range`, + min: 1, + max: size, + step: 1, + }, + graph: { + type: `bar`, + stacked: true, + }, + }; +}; diff --git a/module/utils/sorters/diceSize.mjs b/module/utils/sorters/diceSize.mjs new file mode 100644 index 0000000..dd6ae80 --- /dev/null +++ b/module/utils/sorters/diceSize.mjs @@ -0,0 +1,5 @@ +export function diceSizeSorter(a, b) { + const aInt = Number(a.slice(1)); + const bInt = Number(b.slice(1)); + return Math.sign(aInt - bInt); +}; diff --git a/public/templates/Apps/TableCreator.hbs b/public/templates/Apps/TableCreator.hbs index b32e950..8459de1 100644 --- a/public/templates/Apps/TableCreator.hbs +++ b/public/templates/Apps/TableCreator.hbs @@ -17,6 +17,7 @@ diff --git a/public/templates/Apps/StatsViewer/tableSelect.hbs b/public/templates/Apps/common/tableSelect.hbs similarity index 100% rename from public/templates/Apps/StatsViewer/tableSelect.hbs rename to public/templates/Apps/common/tableSelect.hbs