Module:Autocalctable

-- --|Description : Autocalctable --|Adds summation/average/min/max values of a column of a table imported from json/module/csv page --|Syntax : --| --|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 getArgs = require("Dev:Arguments").getArgs local csv = require("Dev:Csv") local json = require("Dev:Json") --% 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 --% 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 function getTable(sPage,sType) if (sPage) then if sType =="lua" then return require(sPage) end local oData = mw.title.new( sPage):getContent if oData then if sType =="json" then return json.decode(oData) end if sType =="csv" then return csv.convertToLua(sPage) end end end 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 sTag local storedData = {} local calc = {sum={0},avg={0},min={0},max={0},elements = {}} for i,v in ipairs(arrColumns) do        sTag = "td" hTable:tag( 'tr') for sKey,sData in ipairs(arrColumns[i]) do           storedData[sKey] = storedData[sKey] or {} if (i==1) then sTag = "th" end hTable:tag( sTag ) :wikitext(sData ) -- //gets second row because the first one is the heading if tonumber(sData) and i>1 then table.insert(storedData[sKey],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,sData 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