Module:Autocalctable
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Autocalctable/doc
--|Description : Autocalctable
--|Adds summation/average/min/max values of a column of a table imported from json/module/csv page
--|Syntax :
--|{{#invoke:Autotablecalc|page=pagename|type=datatype|calc=calculationtype}}
--|Where calc = sum/avg/min/max - can be more than one separated by commas ,e.g. calc=sum,avg
--| pagename = name of page/module
--| datatype = json or lua or cvs
local p = {}
local csv = require("Dev:Csv")
local json = require("Dev:Json")
local getArgs = require("Dev:Arguments").getArgs
--% Extracts table columns containing numbers
--@ sPage (string) A page containing the table e.g Module:Scores.json
--@ sType (string) The type of data contained in the page (csv, json, lua) -lua table
--: (string) A table containing calculated columns
local function getTable(sPage, sType)
if sPage then
if sType == "lua" then
return require(sPage)
elseif sType == "csv" then
return csv.convertToLua(sPage)
end
local oData = mw.title.new(sPage):getContent()
if oData and sType == "json" then
return json.decode(oData)
end
end
end
--% Entry point - Creates a table with automatically calculated columns
--@ frame (table) A scribunto frame
--: (string) A table containing calculated columns
function p.main(frame)
local args = getArgs(frame)
local sPageName = args.page
local sType = args.type
local calculations = args.calc
local calcTable = getTable(sPageName, sType)
return p.createHtmlTable(calcTable, calculations)
end
--% Creates an html table
--@ arrColumns (string) A column containing numbers
--@ calculations (string) The types of calculations to perform (avg, min, max, sum)
--: (string) An html table containing calculated columns
function p.createHtmlTable(arrColumns, calculations)
if not arrColumns then
return
end
local hTable = mw.html.create("table")
local storedData = {}
local calc = {sum = {0}, avg = {0}, min = {0}, max = {0}, elements = {}}
for i in ipairs(arrColumns) do
local sTag = i == 1 and "th" or "td"
hTable:tag("tr")
for sKey, sData in ipairs(arrColumns[i]) do
storedData[sKey] = storedData[sKey] or {}
hTable:tag(sTag)
:wikitext(sData)
-- //gets second row because the first one is the heading
if tonumber(sData) and i > 1 then
storedData[sKey][#storedData[sKey] + 1] = tonumber(sData)
end
end
end
local val
for index, dataTable in pairs(storedData) do
for _, value in pairs(dataTable) do
val = value or 0
calc.sum[index] = (calc.sum[index] or 0) + val
calc.min[index] = calc.min[index] or 0
calc.max[index] = calc.max[index] or 0
calc.avg[index] = calc.avg[index] or 0
if calc.min[index] >= val then
calc.min[index] = val
end
if calc.max[index] <= val then
calc.max[index] = val
end
end
calc.elements[index] = #dataTable
if calc.sum[index] > 0 then
calc.avg[index] = calc.sum[index] / #dataTable
end
end
local calcTable = mw.text.split(calculations or "", ",")
local bFlag = true
local trNode
for _, calctype in pairs(calcTable) do
if calc[calctype] then
trNode = mw.html.create("tr")
for sKey in ipairs(arrColumns[1]) do
trNode:tag("td")
:wikitext(calc[calctype][sKey])
end
if bFlag then
trNode:css("border-top", "thick double #ff0000")
bFlag = false
end
hTable:node(trNode):done()
end
end
hTable:addClass("wikitable")
hTable:done()
return hTable
end
return p