Module:Autocalctable

From The Satanic Wiki
Revision as of 16:40, 24 April 2021 by Mediawiki>Magiczocker01
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Autocalctable/doc

--<pre>
--|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