Module:Sandbox/User:4madness/ParamSum: Difference between revisions
Jump to navigation
Jump to search
m (Cleaned code, changed and expanded class syntax to cater for conditionals, added errors, added named args for numbered args, changed param filtering) |
(No difference)
|
Revision as of 06:00, 3 March 2019
Documentation for this module may be created at Module:Sandbox/User:4madness/ParamSum/doc
--
-- Accepts data in the format "param=pval1|param2=pval2!param=pval2|param2=pval2!..." and sums each value together
-- <nowiki>
--
local yesno = require( 'Module:Yesno' )
local hc = require('Module:Paramtest').has_content
p = {}
function p.table(frame)
local args = frame:getParent().args
local data = args[1] or args.data or nil
local selected = args[2] or args.selected or nil
args.html = yesno(args.html)
if (data == nil) then
return '<span class="error">No data provided.</span>'
end
if (selected == nil) then
return '<span class="error">No selected value list provided.</span>'
elseif (not hc(selected)) then
return '<span class="error">Selected value list cannot be empty.</span>'
end
return p._table(data,selected,args)
end
function p._table(data,selected,args)
args = args or {}
local sum_table = {}
selected = mw.text.trim(selected)
-- initialize sums to zero
-- keys not in this table are skipped
for k in mw.text.gsplit(selected, '%s*,%s*') do
sum_table[k] = 0
end
local rowcount = 0
for oneRawRow in string.gmatch(data, '([^!]+)') do -- split by '!' symbols
oneRawRow = mw.text.trim(oneRawRow)
if (hc(oneRawRow)) then
rowcount = rowcount + 1
for k, v in string.gmatch(oneRawRow, '([^|]*)=([^|]*)') do
k = mw.text.trim(k)
if (sum_table[k] ~= nil) then
sum_table[k] = sum_table[k] + tonumber(v)
end
end
end
end
-- save rowcount to special ID
sum_table['#'] = rowcount
if (args.html) then
return p._table_html(sum_table,selected,args)
else
return p._table_wikitable(sum_table,selected,args)
end
end
function p._table_html(sum_table,selected,args)
local html = mw.html.create('tr')
local classes = ''
for k in mw.text.gsplit(selected, '%s*,%s*') do
classes = p._parse_conditional_classes(sum_table[k], args[k .. " class"], sum_table['#']) or ''
if (classes ~= '') then
html = html:tag('td'):addClass(classes):wikitext(sum_table[k]):done()
else
html = html:tag('td'):wikitext(sum_table[k]):done()
end
end
return html:done()
end
function p._table_wikitable(sum_table,selected,args)
local ret = ''
for k in mw.text.gsplit(selected, '%s*,%s*') do
local classes = p._parse_conditional_classes(sum_table[k], args[k .. " class"], sum_table['#']) or ''
ret = ret .. (ret ~= '' and '||' or '')
.. (classes ~= '' and (' class="' .. classes .. '" |') or '')
.. sum_table[k]
end
return ret
end
function p._parse_conditional_classes(val, classdefs, count)
if (not hc(classdefs)) then
return '' -- shortcut for no content
elseif (not string.find(classdefs, ':', 1, true)) then
return classdefs -- shortcut if no conditionals found
end
local ret = ''
for class in mw.text.gsplit(classdefs, '%s+') do
local parts = mw.text.split(class, ':')
-- if class has a condition, add only if condition is met
if (#parts > 1) then
if (p._meets_condition(parts[1], val, count)) then
ret = ret .. parts[2] .. ' '
end
else
ret = ret .. parts[1] .. ' ' -- add conditionless classes
end
end
return ret
end
-- condtions are of format "<operation><compare-value>"
-- conditions of format "<compare-value>", assume "eq" for the operation
-- if "<compare-value>" is "#", the count will be used as the compare value
function p._meets_condition(condition, val, count)
if (condition == nil or val == nil) then
return nil
elseif (condition == '') then
return true
end
local op = string.match(condition, '^[^%d#]+')
local compare = string.sub(condition, #op+1)
if (compare == '#') then
if (count == nil) then
return nil
end
compare = count
end
if (op == 'eq' or op == '') then
return val == tonumber(compare)
elseif (op == 'gt') then
return val > tonumber(compare)
elseif (op == 'lt') then
return val < tonumber(compare)
elseif (op == 'neq') then
return val ~= tonumber(compare)
elseif (op == 'gteq') then
return val >= tonumber(compare)
elseif (op == 'lteq') then
return val <= tonumber(compare)
end
return false
end
return p