Module:AbilityTable: Difference between revisionsGive feedback
Merge analyze_charges into charges_cells; move human notes to framework level with extensible table; Notes column auto-injected when notes exist (with help from vergir-bot LLM) |
Restructure globals order; Notes declared in charges headers; add CSS classes to table elements (with help from vergir-bot LLM) |
||
| Line 12: | Line 12: | ||
-- determine whether an ability appears in the table. | -- determine whether an ability appears in the table. | ||
-- | -- | ||
-- 2. | -- 2. Add a matching entry to extra_columns: | ||
-- - headers: ordered list of column header strings. | |||
-- Include "Notes" if this stat generates notes. | |||
-- - headers: ordered list of column header strings | |||
-- | |||
-- - get_cells: function(ability) -> { ["Column Name"] = value } | -- - get_cells: function(ability) -> { ["Column Name"] = value } | ||
-- The ability is guaranteed to match the stat. | -- The ability is guaranteed to match the stat. | ||
-- | -- Omit a key or return nil to show "—" in that cell. | ||
-- If no extra_columns entry is added, only Hero and Ability | -- If no extra_columns entry is added, only Hero and Ability | ||
-- columns are shown (plus Notes if human notes exist). | -- columns are shown (plus Notes if human notes exist for the stat). | ||
-- | -- | ||
-- 3. Optionally add | -- 3. Optionally add human-authored notes to human_notes: | ||
-- | -- human_notes["stat"]["Ability Name"] = "Note text." | ||
-- Notes are appended to any renderer-generated note automatically. | |||
-- | -- | ||
-- 4. Optionally add | -- 4. Optionally add entries to column_suffix to append a unit | ||
-- | -- string (e.g. "s", "%") after cell values in specific columns. | ||
-- ============================================================ | -- ============================================================ | ||
| Line 34: | Line 32: | ||
local GameData = require("Module:GameData") | local GameData = require("Module:GameData") | ||
-- Maps lowercase friendly stat names to internal AbilityData property keys. | -- ============================================================ | ||
-- stat_to_props | |||
-- Maps lowercase friendly stat names to internal AbilityData | |||
-- property keys used to filter which abilities appear. | |||
-- ============================================================ | |||
local stat_to_props = { | local stat_to_props = { | ||
["charges"] = { "AbilityCharges" }, | ["charges"] = { "AbilityCharges" }, | ||
} | } | ||
-- | -- ============================================================ | ||
-- human_notes | |||
-- Editor-authored notes appended to the Notes column. | |||
-- Keyed first by stat name, then by ability display Name. | |||
-- ============================================================ | |||
-- | |||
-- Keyed by stat name, then by ability display Name. | |||
local human_notes = { | local human_notes = { | ||
["charges"] = { | ["charges"] = { | ||
| Line 78: | Line 78: | ||
-- Per-stat cell renderers | -- Per-stat cell renderers | ||
-- Each function receives a guaranteed-matching ability record | -- Each function receives a guaranteed-matching ability record | ||
-- and returns { ["Column Name"] = value } | -- and returns { ["Column Name"] = value }. | ||
-- Human notes | -- Human notes are appended by the framework, not here. | ||
-- ============================================================ | -- ============================================================ | ||
| Line 133: | Line 133: | ||
end | end | ||
-- ============================================================ | |||
-- extra_columns | |||
-- Declares headers and cell renderer for each stat. | |||
-- ============================================================ | |||
local extra_columns = { | local extra_columns = { | ||
["charges"] = { | ["charges"] = { | ||
headers = { "Charges", "Time Between Charges" }, | headers = { "Charges", "Time Between Charges", "Notes" }, | ||
get_cells = charges_cells, | get_cells = charges_cells, | ||
}, | }, | ||
} | |||
-- ============================================================ | |||
-- column_suffix | |||
-- Unit strings appended to non-nil cell values by column name. | |||
-- ============================================================ | |||
local column_suffix = { | |||
["Time Between Charges"] = "s", | |||
} | } | ||
| Line 195: | Line 207: | ||
end | end | ||
local lookup | local lookup = build_hero_lookup() | ||
local spec | local spec = extra_columns[stat] | ||
local headers | local headers = spec and spec.headers or {} | ||
local get_cells | local get_cells = spec and spec.get_cells or function() return {} end | ||
local stat_notes | local stat_notes = human_notes[stat] | ||
local abilities = GameData.get_entities(GameData.Dataset.ABILITIES, internal_keys) | local abilities = GameData.get_entities(GameData.Dataset.ABILITIES, internal_keys) | ||
| Line 226: | Line 238: | ||
end) | end) | ||
-- Determine | -- Determine final header list. "Notes" is included if declared in headers | ||
-- | -- (meaning the renderer may produce notes) or if human notes exist for | ||
local | -- this stat. Either way it appears exactly once at the end. | ||
local has_notes_header = false | |||
local final_headers = {} | |||
for _, h in ipairs(headers) do | |||
if h == "Notes" then | |||
has_notes_header = true | |||
else | |||
table.insert(final_headers, h) | |||
end | end | ||
end | end | ||
local needs_notes = has_notes_header or stat_notes ~= nil | |||
if needs_notes then | |||
local | table.insert(final_headers, "Notes") | ||
end | |||
if needs_notes then table.insert(final_headers, "Notes") end | |||
-- Render wikitable | -- Render wikitable | ||
local out = {} | local out = {} | ||
local | table.insert(out, '{| class="wikitable sortable ability-table"') | ||
local header_cells = '! class="ability-table-col-hero" | Hero' | |||
.. ' !! class="ability-table-col-ability" | Ability' | |||
for _, h in ipairs(final_headers) do | |||
local cls = "ability-table-col-" .. h:lower():gsub("%s+", "-") | |||
header_cells = header_cells .. ' !! class="' .. cls .. '" | ' .. h | |||
end | end | ||
table.insert(out, header_cells) | |||
table.insert(out, | |||
for _, ability in ipairs(filtered) do | for _, ability in ipairs(filtered) do | ||
| Line 266: | Line 279: | ||
} | } | ||
local extra = get_cells(ability) | |||
local extra | |||
-- Append human note to any renderer-generated note | -- Append human note to any renderer-generated note | ||
| Line 275: | Line 287: | ||
end | end | ||
local row_cells = '| class="ability-table-cell-hero" | ' .. hero_cell | |||
.. ' || class="ability-table-cell-ability" | ' .. ability_cell | |||
for _, header in ipairs(final_headers) do | for _, header in ipairs(final_headers) do | ||
local value = extra[header] | local value = extra[header] | ||
local cls = "ability-table-cell-" .. header:lower():gsub("%s+", "-") | |||
local content | |||
if value ~= nil then | if value ~= nil then | ||
local suffix = column_suffix[header] or "" | local suffix = column_suffix[header] or "" | ||
content = value .. suffix | |||
else | else | ||
content = "—" | |||
end | end | ||
row_cells = row_cells .. ' || class="' .. cls .. '" | ' .. content | |||
end | end | ||
table.insert(out, "|-") | table.insert(out, "|-") | ||
table.insert(out, | table.insert(out, row_cells) | ||
end | end | ||