More actions
Content deleted Content added
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
(42 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
local p = {} |
local p = {} |
||
-- Column mappings |
|||
local columns = { |
|||
op = 1, |
|||
celestial_nouns = 2, |
|||
celestial_verbs = 3, |
|||
adjectives = 4, |
|||
adverbs = 5, |
|||
pronouns = 6, |
|||
propositions = 7, |
|||
conjunctives = 8, |
|||
articles = 9, |
|||
flame_verbs = 10, |
|||
flame_nouns = 11, |
|||
storm_verbs = 12, |
|||
storm_nouns = 13, |
|||
life_verbs = 14, |
|||
life_nouns = 15, |
|||
necro_verbs = 16, |
|||
necro_nouns = 17, |
|||
nature_verbs = 18, |
|||
nature_nouns = 19 |
|||
} |
|||
local backgrounds = { |
|||
op = '#f9f06b1A', |
|||
celestial_nouns = '#dc8add1A', |
|||
celestial_verbs = '#dc8add1A', |
|||
adjectives = '#dc8add1A', |
|||
adverbs = '#dc8add1A', |
|||
pronouns = '#dc8add1A', |
|||
propositions = '#dc8add1A', |
|||
conjunctives = '#dc8add1A', |
|||
articles = '#dc8add1A', |
|||
flame_verbs = '#f661511A', |
|||
flame_nouns = '#f661511A', |
|||
storm_verbs = '#99c1f11A', |
|||
storm_nouns = '#99c1f11A', |
|||
life_verbs = '#ffffff1A', |
|||
life_nouns = '#ffffff1A', |
|||
necro_verbs = '#77767b1A', |
|||
necro_nouns = '#77767b1A', |
|||
nature_verbs = '#8ff0a41A', |
|||
nature_nouns = '#8ff0a41A' |
|||
} |
|||
local backgrounds_even = { |
|||
op = '#e5a50a1A', |
|||
celestial_nouns = '#6135831A', |
|||
celestial_verbs = '#6135831A', |
|||
adjectives = '#6135831A', |
|||
adverbs = '#6135831A', |
|||
pronouns = '#6135831A', |
|||
propositions = '#6135831A', |
|||
conjunctives = '#6135831A', |
|||
articles = '#6135831A', |
|||
flame_verbs = '#a51d2d1A', |
|||
flame_nouns = '#a51d2d1A', |
|||
storm_verbs = '#1a5fb41A', |
|||
storm_nouns = '#1a5fb41A', |
|||
life_verbs = '#9a99961A', |
|||
life_nouns = '#9a99961A', |
|||
necro_verbs = '#0000001A', |
|||
necro_nouns = '#0000001A', |
|||
nature_verbs = '#26a2691A', |
|||
nature_nouns = '#26a2691A' |
|||
} |
|||
local links = { |
|||
flame_verbs = '{{L|Class|Flame Mage|Flame Verbs}}', |
|||
flame_nouns = '{{L|Class|Flame Mage|Flame Nouns}}', |
|||
storm_verbs = '{{L|Class|Storm Mage|Storm Verbs}}', |
|||
storm_nouns = '{{L|Class|Storm Mage|Storm Nouns}}', |
|||
life_verbs = '{{L|Class|Life Mage|Life Verbs}}', |
|||
life_nouns = '{{L|Class|Life Mage|Life Nouns}}', |
|||
necro_verbs = '{{L|Class|Necromancer|Necro Verbs}}', |
|||
necro_nouns = '{{L|Class|Necromancer|Necro Nouns}}', |
|||
nature_verbs = '{{L|Class|Nature Mage|Nature Verbs}}', |
|||
nature_nouns = '{{L|Class|Nature Mage|Nature Nouns}}' |
|||
} |
|||
-- Helper function to parse the source table |
|||
local function parseTable(frame, output) |
|||
local source = mw.text.split(frame:preprocess('{{:MediaWiki:ESTable}}'), '\n') |
|||
local data = {} |
|||
for i, line in ipairs(source) do |
|||
if line:match('^|%-') then |
|||
-- Skip separator lines |
|||
elseif line:match('^|') then |
|||
local row = {} |
|||
for cell in line:gmatch('|%s*([^||]+)%s*') do |
|||
table.insert(row, cell:match('^%s*(.-)%s*$')) |
|||
-- output = output .. cell .. '\n' |
|||
end |
|||
if #row > 0 then |
|||
table.insert(data, row) |
|||
end |
|||
end |
|||
end |
|||
return data, output |
|||
end |
|||
-- Helper function to trim whitespace and new lines |
|||
local function trim(s) |
|||
return s:match('^%s*(.-)%s*$') |
|||
end |
|||
local function supertrim(s) |
|||
return s:match('^%s*(.-)%s*$'):gsub('%d', '') |
|||
end |
|||
-- Main function to generate filtered table |
|||
function p.filter(frame) |
|||
local output = '' |
|||
local args = frame.args |
|||
local data, output = parseTable(frame, output) |
|||
-- if true then |
|||
-- return data |
|||
-- end |
|||
local selectedCols = {} |
|||
if args then |
|||
-- Trim whitespace from args |
|||
for k, v in pairs(args) do |
|||
args[k] = trim(v) |
|||
end |
|||
-- Remove empty arguments |
|||
for k, v in pairs(args) do |
|||
if v == '' then |
|||
args[k] = nil |
|||
end |
|||
end |
|||
-- Determine which columns to show |
|||
for k, v in pairs(args) do |
|||
if ((v ~= '') and columns[k]) then |
|||
table.insert(selectedCols, {name = k, index = columns[k]}) |
|||
end |
|||
end |
|||
end |
|||
local bg = (args.bg ~= '') |
|||
-- Sort columns by their original index |
|||
table.sort(selectedCols, function(a, b) return a.index < b.index end) |
|||
-- for _, col in ipairs(selectedCols) do |
|||
-- output = output .. ' !! ' .. tostring(col.index) |
|||
-- end |
|||
-- output = output .. '\n\n' |
|||
-- Generate output table |
|||
output = output .. '{| class="mw-collapsible mw-collapsed wikitable sortable"\n|+ style=white-space:nowrap | Elder Sorcery Words\n' |
|||
-- Header row |
|||
-- output = output .. '! OP' |
|||
-- for _, col in ipairs(selectedCols) do |
|||
-- local header = col.name:gsub("_", " "):gsub("^%l", string.upper) |
|||
-- output = output .. ' !! ' .. header |
|||
-- end |
|||
-- output = output .. '\n' |
|||
-- Data rows |
|||
local header = true |
|||
for _, row in ipairs(data) do |
|||
if (#row > 0) and (#selectedCols > 0) then |
|||
output = output .. '\n\n|-\n\n' |
|||
local dontskip = false |
|||
row_content = '' |
|||
for _, col in ipairs(selectedCols) do |
|||
if header then |
|||
d = '!' |
|||
else |
|||
d = '|' |
|||
end |
|||
content = d |
|||
op = tonumber(row[1]) or 0 |
|||
if bg then |
|||
if op % 2 == 0 then |
|||
content = content .. ' style="background-color: ' .. backgrounds_even[col.name] .. '" |' |
|||
else |
|||
content = content .. ' style="background-color: ' .. backgrounds[col.name] .. '" |' |
|||
end |
|||
-- content = content .. ' style="background-color: ' .. backgrounds[col.name] .. '" |' |
|||
end |
|||
word = tostring(row[col.index]) |
|||
if links[word] then |
|||
word = frame:preprocess(links[word]) |
|||
end |
|||
if supertrim(word) ~= '' then |
|||
dontskip = true |
|||
end |
|||
content = content .. ' ' .. word .. ' ' .. d |
|||
row_content = row_content .. content |
|||
end |
|||
if dontskip then |
|||
output = output .. row_content |
|||
end |
|||
output = output:sub(1, -3) |
|||
-- output = output .. '\n' |
|||
end |
|||
if header then |
|||
header = false |
|||
end |
|||
end |
|||
output = output .. '\n|}' |
|||
return output |
|||
end |
|||
-- NEW CONTENT |
|||
-- ----------- |
|||
local esw = require('Module:ESWords') |
local esw = require('Module:ESWords') |
||
Line 229: | Line 13: | ||
local function fixInputs(elements, parts, ops) |
local function fixInputs(elements, parts, ops) |
||
if elements == " |
if elements == "all" then |
||
elements = {} |
elements = {} |
||
for elementName, _ in pairs(words) do |
for elementName, _ in pairs(words) do |
||
Line 236: | Line 20: | ||
end |
end |
||
if parts == " |
if parts == "all" then |
||
parts = {} |
parts = {} |
||
local firstElement = next(words) |
local firstElement = next(words) |
||
Line 246: | Line 30: | ||
end |
end |
||
if ops == " |
if ops == "all" then |
||
ops = {} |
ops = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} |
||
local firstElement = next(words) |
|||
if firstElement then |
|||
local firstPart = next(words[firstElement]) |
|||
if firstPart then |
|||
for opLevel, _ in pairs(words[firstElement][firstPart]) do |
|||
table.insert(ops, opLevel) |
|||
end |
|||
end |
|||
end |
|||
end |
end |
||
Line 341: | Line 116: | ||
local outWords = filterWords(elements, parts, ops) |
local outWords = filterWords(elements, parts, ops) |
||
local tableTitle = '{{L|Core|Elder Sorcery Words|u=1}}' |
|||
if #elements == 1 then |
|||
-- If there's only one element, part, and op, use a more specific title |
|||
local elementName = elements[1]:gsub("_", " "):gsub("^%l", string.upper) |
|||
if elementName == "Necro" then |
|||
elementName = "Necromancy" |
|||
end |
|||
tableTitle = elementName .. ' ' .. tableTitle |
|||
end |
|||
if #ops == 1 then |
|||
-- If there's only one OP level, use it in the title |
|||
tableTitle = 'OP ' .. tostring(ops[1]) .. ' ' .. tableTitle |
|||
end |
|||
out = '{| class="wikitable sortable"\n|+ style=white-space:nowrap | ' .. frame:preprocess(tableTitle) .. '\n' |
|||
-- Header row |
-- Header row |
||
local rowNum = 0 |
local rowNum = 0 |
||
out = out .. '!' .. bgStr(rowNum, 'op') .. 'OP' |
out = out .. '!' .. bgStr(rowNum, 'op') .. 'OP' |
||
local actualColumns = {} |
local actualColumns = {} |
||
table.sort(elements, function(a, b) return a < b end) |
|||
for _, elementName in pairs(elements) do |
for _, elementName in pairs(elements) do |
||
table.sort(parts, function(a, b) return a < b end) |
|||
for _, part in pairs(parts) do |
for _, part in pairs(parts) do |
||
if outWords[elementName] and outWords[elementName][part] and (#outWords[elementName][part] > 0) then |
if outWords[elementName] and outWords[elementName][part] and (#outWords[elementName][part] > 0) then |
||
Line 353: | Line 144: | ||
if elementTitle == "Necro" then |
if elementTitle == "Necro" then |
||
elementTitle = "Necromancy" |
elementTitle = "Necromancy" |
||
titleLink = "Necromancer" |
|||
end |
end |
||
local partTitle = part:gsub("_", " "):gsub("^%l", string.upper) |
local partTitle = part:gsub("_", " "):gsub("^%l", string.upper) |
||
local titleText = elementTitle .. ' ' .. partTitle |
local titleText = elementTitle .. ' ' .. partTitle |
||
local title = '{{L|Class|' .. titleLink .. '|' .. titleText .. '}}' |
local title = '{{L|Class|' .. titleLink .. '|' .. titleText .. '}}' |
||
if elementName == "celestial" then |
|||
title = titleText |
|||
end |
|||
out = out .. ' !!' .. bgStr(rowNum, elementName) .. frame:preprocess(title) |
out = out .. ' !!' .. bgStr(rowNum, elementName) .. frame:preprocess(title) |
||
table.insert(actualColumns, { |
table.insert(actualColumns, { |
||
Line 384: | Line 178: | ||
end |
end |
||
numRows = math.max(numRows, columnNumRows) |
numRows = math.max(numRows, columnNumRows) |
||
table.sort(columnWords, function(a, b) return a < b end) |
|||
-- Store the words for this column and op level |
-- Store the words for this column and op level |
||
wordCollections[opLevel][columnElement .. "_" .. columnPart] = { |
wordCollections[opLevel][columnElement .. "_" .. columnPart] = { |
||
Line 406: | Line 201: | ||
if wordCollections[opLevel][columnElement .. "_" .. columnPart] and wordCollections[opLevel][columnElement .. "_" .. columnPart].words[rowIndex] then |
if wordCollections[opLevel][columnElement .. "_" .. columnPart] and wordCollections[opLevel][columnElement .. "_" .. columnPart].words[rowIndex] then |
||
cellContent = wordCollections[opLevel][columnElement .. "_" .. columnPart].words[rowIndex] |
cellContent = wordCollections[opLevel][columnElement .. "_" .. columnPart].words[rowIndex] |
||
end |
|||
if cellContent:find("%^") then |
|||
cellContent = "''" .. cellContent:gsub("%^", "") .. "''" |
|||
cellContent = frame:preprocess(cellContent) |
|||
end |
end |
||
-- Add the cell content to the output |
-- Add the cell content to the output |
||
Line 417: | Line 216: | ||
end |
end |
||
function p. |
function p.get(frame) |
||
-- This function will be the main entry point to get the table |
|||
return elements .. ' ' .. parts .. ' ' .. ops |
|||
local args = frame.args |
|||
local elements = args.elements or 'all' |
|||
if elements ~= 'all' then |
|||
elements = mw.text.split(elements, '%s') |
|||
end |
|||
local parts = args.parts or 'all' |
|||
if parts ~= 'all' then |
|||
parts = mw.text.split(parts, '%s') |
|||
end |
|||
local ops = args.ops or 'all' |
|||
if ops ~= 'all' then |
|||
ops = mw.text.split(ops, '%s') |
|||
for i, op in ipairs(ops) do |
|||
ops[i] = tonumber(op) |
|||
end |
|||
end |
|||
return p.getTable(frame, elements, parts, ops) |
|||
end |
|||
function p.all(frame) |
|||
return p.getTable(frame, 'all', 'all', {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) |
|||
end |
|||
function p.testInput(frame) |
|||
local args = frame.args |
|||
local out = '' |
|||
for k, v in pairs(args) do |
|||
out = out .. k .. ': ' .. tostring(v) .. '\n' |
|||
end |
|||
return out |
|||
end |
end |
||
Latest revision as of 20:25, 31 March 2025
Documentation for this module may be created at Module:ESTable/doc
local p = {}
local esw = require('Module:ESWords')
local words = esw.words()
local function contains(tbl, val)
for _, v in ipairs(tbl) do
if v == val then return true end
end
return false
end
local function fixInputs(elements, parts, ops)
if elements == "all" then
elements = {}
for elementName, _ in pairs(words) do
table.insert(elements, elementName)
end
end
if parts == "all" then
parts = {}
local firstElement = next(words)
if firstElement then
for partName, _ in pairs(words[firstElement]) do
table.insert(parts, partName)
end
end
end
if ops == "all" then
ops = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
end
-- Normalize inputs to tables if they are not already
if type(elements) ~= "table" then
elements = { elements }
end
if type(parts) ~= "table" then
parts = { parts }
end
if type(ops) ~= "table" then
ops = { ops }
end
return elements, parts, ops
end
local function filterWords(elements, parts, ops)
local outWords = {}
for elementName, elementData in pairs(words) do
if contains(elements, elementName) then
outWords[elementName] = {}
for _, part in ipairs(parts) do
if elementData[part] then
outWords[elementName][part] = {}
for _, op in ipairs(ops) do
if elementData[part][op] then
outWords[elementName][part][op] = elementData[part][op]
end
end
end
end
end
end
return outWords
end
local bgs = {
even = {
op = '#e5a50a1A',
celestial = '#6135831A',
flame = '#a51d2d1A',
storm = '#1a5fb41A',
life = '#9a99961A',
necro = '#0000001A',
nature = '#26a2691A',
},
odd = {
op = '#f9f06b1A',
celestial = '#dc8add1A',
flame = '#f661511A',
storm = '#99c1f11A',
life = '#ffffff1A',
necro = '#77767b1A',
nature = '#8ff0a41A',
}
}
local function bgHex(rowNum, col)
-- Determine the background color based on the row number and column type
local bgColor
if rowNum % 2 == 0 then
-- Even row
bgColor = bgs.even[col]
else
-- Odd row
bgColor = bgs.odd[col]
end
return bgColor or '#ffffff1A' -- Fallback to white if no color is defined
end
local function bgStr(rowNum, col)
-- Generate the background style string for a given row and column
local bgColor = bgHex(rowNum, col)
return ' style="background-color: ' .. bgColor .. '" | '
end
function p.getWords(frame, elements, parts, ops)
elements, parts, ops = fixInputs(elements, parts, ops)
return filterWords(elements, parts, ops)
end
function p.getTable(frame, elements, parts, ops)
elements, parts, ops = fixInputs(elements, parts, ops)
local outWords = filterWords(elements, parts, ops)
local tableTitle = '{{L|Core|Elder Sorcery Words|u=1}}'
if #elements == 1 then
-- If there's only one element, part, and op, use a more specific title
local elementName = elements[1]:gsub("_", " "):gsub("^%l", string.upper)
if elementName == "Necro" then
elementName = "Necromancy"
end
tableTitle = elementName .. ' ' .. tableTitle
end
if #ops == 1 then
-- If there's only one OP level, use it in the title
tableTitle = 'OP ' .. tostring(ops[1]) .. ' ' .. tableTitle
end
out = '{| class="wikitable sortable"\n|+ style=white-space:nowrap | ' .. frame:preprocess(tableTitle) .. '\n'
-- Header row
local rowNum = 0
out = out .. '!' .. bgStr(rowNum, 'op') .. 'OP'
local actualColumns = {}
table.sort(elements, function(a, b) return a < b end)
for _, elementName in pairs(elements) do
table.sort(parts, function(a, b) return a < b end)
for _, part in pairs(parts) do
if outWords[elementName] and outWords[elementName][part] and (#outWords[elementName][part] > 0) then
local elementTitle = elementName:gsub("_", " "):gsub("^%l", string.upper)
local titleLink = elementName .. " Mage"
if elementTitle == "Necro" then
elementTitle = "Necromancy"
titleLink = "Necromancer"
end
local partTitle = part:gsub("_", " "):gsub("^%l", string.upper)
local titleText = elementTitle .. ' ' .. partTitle
local title = '{{L|Class|' .. titleLink .. '|' .. titleText .. '}}'
if elementName == "celestial" then
title = titleText
end
out = out .. ' !!' .. bgStr(rowNum, elementName) .. frame:preprocess(title)
table.insert(actualColumns, {
element = elementName,
part = part
})
end
end
end
rowNum = rowNum + 1
local opRowNum = 1
local wordCollections = {}
-- Collect all words for each OP level
for opLevel = 1, 10 do
wordCollections[opLevel] = {}
local numRows = 0
for _, column in ipairs(actualColumns) do
local columnElement = column.element
local columnPart = column.part
local columnNumRows = 0
local columnWords = {}
if outWords[columnElement] and outWords[columnElement][columnPart] and outWords[columnElement][columnPart][opLevel] then
columnWords = outWords[columnElement][columnPart][opLevel]
columnNumRows = #columnWords
end
numRows = math.max(numRows, columnNumRows)
table.sort(columnWords, function(a, b) return a < b end)
-- Store the words for this column and op level
wordCollections[opLevel][columnElement .. "_" .. columnPart] = {
words = columnWords,
count = columnNumRows
}
end
-- Now we have the max number of rows for this OP level, we can proceed to build the table
-- Iterate over each column to build the rows for this OP level
for rowIndex = 1, numRows do
out = out .. '\n|-\n' -- Start a new row
if rowIndex == 1 then
out = out .. '|rowspan="' .. tostring(numRows) .. '" ' ..bgStr(opRowNum, 'op') .. opLevel
opRowNum = opRowNum + 1
else
out = out .. ' '
end
for _, column in ipairs(actualColumns) do
local columnElement = column.element
local columnPart = column.part
local cellContent = ''
if wordCollections[opLevel][columnElement .. "_" .. columnPart] and wordCollections[opLevel][columnElement .. "_" .. columnPart].words[rowIndex] then
cellContent = wordCollections[opLevel][columnElement .. "_" .. columnPart].words[rowIndex]
end
if cellContent:find("%^") then
cellContent = "''" .. cellContent:gsub("%^", "") .. "''"
cellContent = frame:preprocess(cellContent)
end
-- Add the cell content to the output
out = out .. '\n|' .. bgStr(rowNum, columnElement) .. cellContent
end
rowNum = rowNum + 1
end
end
out = out .. '\n|}'
return out
end
function p.get(frame)
-- This function will be the main entry point to get the table
local args = frame.args
local elements = args.elements or 'all'
if elements ~= 'all' then
elements = mw.text.split(elements, '%s')
end
local parts = args.parts or 'all'
if parts ~= 'all' then
parts = mw.text.split(parts, '%s')
end
local ops = args.ops or 'all'
if ops ~= 'all' then
ops = mw.text.split(ops, '%s')
for i, op in ipairs(ops) do
ops[i] = tonumber(op)
end
end
return p.getTable(frame, elements, parts, ops)
end
function p.all(frame)
return p.getTable(frame, 'all', 'all', {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
end
function p.testInput(frame)
local args = frame.args
local out = ''
for k, v in pairs(args) do
out = out .. k .. ': ' .. tostring(v) .. '\n'
end
return out
end
return p