Jump to content

Module:Infobox power station

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by RexxS (talk | contribs) at 21:48, 17 March 2019 (tidy and simplify). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

--[[
Power supply units
Custom module to autofill four parameters for use in Template:Infobox power station
Parameters are:
ps_units_operational
	→ The number of generation units operational and their nameplate capacity
	→ Example: 3 × 100 MW<br>1 × 110 MW
ps_units_manu_model
	→ The manufacturer and model of the generation units
	→ Example: Vestas V164
ps_units_uc
	→ The number of generation units under construction
	→ Example: 2 × 150 MW<br>1 × 160 MW
ps_units_decommissioned
	→ The number of generation units decommissioned
	→ Example: 1 × 75 MW<br>1 × 70 MW
--]]

local p = {}

local i18n = {
	["langcode"] = "en",
	["op_lbl"] = "Units operational",
	["mm_lbl"] = "Make and model",
	["uc_lbl"] = "Units under const.",
	["dc_lbl"] = "Units decommissioned",
}

-- numerically sort sequential tables whose values contain a number, like "350 MW"
-- sort on first number found
local function numcomp1( x, y )
	x = tonumber( tostring(x):match("%d+") ) or 0
	y = tonumber( tostring(y):match("%d+") ) or 0
	return x < y
end

-- numerically sort sequential tables whose values contain two numbers, like "1 x 350 MW"
-- sort on second number found
local function numcomp2( x, y )
	x = tonumber( tostring(x):match("%d+%D+(%d+)") ) or 0
	y = tonumber( tostring(y):match("%d+%D+(%d+)") ) or 0
	return x < y
end

-- alphabetically sort sequential tables whose values may contain wikilinks.
-- Formats: "[[Link|Text]]" or "[[Link]]" or "Text"
local function linkcomp( a, b )
	-- a = a:gsub("%[%[.*|", ""):gsub("%[%[", ""):gsub("]]","") -> test for best
	a = a:match("%[%[.*|(.*)]]") or a:match("%[%[(.*)]]") or a
	b = b:match("%[%[.*|(.*)]]") or b:match("%[%[(.*)]]") or b
	return a < b
end

--Render monolingual text
local function rendermlt(props, langcode)
	for k, v in ipairs(props) do
		v = v.mainsnak or v
		if v.snaktype == "value" and v.datavalue.value.language == langcode then
			return v.datavalue.value.text
		end
	end
end

p.psunits = function(frame)
	local args = frame.args
	local psu_op = args.ps_units_operational or ""
	local psu_mm = args.ps_units_manu_model or ""
	local psu_uc = args.ps_units_uc or ""
	local psu_dc = args.ps_units_decommissioned or ""
	local qid = args.qid or ""
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return nil end

	local langcode = args.lang or ""
	if langcode == "" then langcode = i18n.langcode end

	local props516 = mw.wikibase.getBestStatements(qid, "P516")
	if #props516 < 1 then return nil end

	local status = {}
	local mm = {}
	local cap = {}
	for i1, v1 in ipairs(props516) do
		local quals = v1.qualifiers
		if quals then
			-- determine status from service retirement/entry/inception
			if quals.P730 and quals.P730[1].snaktype == "value" then
				status[i1] = "dc"
			elseif quals.P729 and quals.P729[1].snaktype == "value" then
				status[i1] = "op"
			elseif quals.P571 and quals.P571[1].snaktype == "value" then
				status[i1] = "uc"
			else
				status[i1] = "unknown"
			end

			-- get manufacturer and model
			local mfr, mqid, mdl
			-- manufacturer
			mqid = (v1.mainsnak.snaktype == "value") and v1.mainsnak.datavalue.value.id
			if mqid then
				-- look for a shortname to use for display label, otherwise use label
				local props1813 = mw.wikibase.getAllStatements(mqid, "P1813")
				local lbl = rendermlt(props1813, langcode) or mw.wikibase.getLabel(mqid)
				local sitelink = mw.wikibase.getSitelink(mqid)
				mfr = sitelink and lbl and ("[[" .. sitelink .. "|" .. lbl .."]]")
					or sitelink and ("[[" .. sitelink .. "]]")
					or lbl
			end
			-- model from codename qualifier (P1638)
			if quals.P1638 then mdl = rendermlt(quals.P1638, langcode) end
			mm[i1] = mfr and mdl and (mfr .. " " .. mdl) or mfr or mdl

			-- get capacity from P2109
			if quals.P2109 and quals.P2109[1].snaktype == "value" then
				cap[i1] = tonumber(quals.P2109[1].datavalue.value.amount) or ""
				-- get qid of unit
				local uqid = (quals.P2109[1].datavalue.value.unit or ""):match("(Q%d+)")
				-- scan table of unit symbols
				local usym = ""
				for i2, v2 in ipairs( mw.wikibase.getAllStatements(uqid, "P5061") ) do
					if v2.mainsnak.snaktype == "value"
					and v2.mainsnak.datavalue.value.language == langcode then
						usym = "&nbsp;" .. v2.mainsnak.datavalue.value.text
						break
					end
				end
				cap[i1] = cap[i1] .. usym
			end
		end
	end

	-- construct set of manufacturers and models of operational units
	-- key is the manufacturer + model and value is count of that.
	local opmm = {}
	for i, v in ipairs(status) do
		if v == "op" and mm[i] then opmm[mm[i]] = (opmm[mm[i]] or 0) + 1 end
	end
	-- construct html string from the set of manufacturers and models
	-- first make a sequential table
	local opmmseq = {}
	for k, v in pairs(opmm) do
		opmmseq[#opmmseq+1] = k .. " (" .. v .. ")"
	end
	table.sort(opmmseq, linkcomp)
	if psu_mm == "" then psu_mm = table.concat(opmmseq, "<br>") end

	-- construct sets of capacities of operational units (opcap),
	-- units under construction (uccap), and decommissioned {dccap)]
	-- key is the capacity and value is count of that capacity.
	local opcap, uccap, dccap = {}, {}, {}
	for i, v in ipairs(status) do
		if v == "uc" and cap[i] then uccap[cap[i]] = (uccap[cap[i]] or 0) + 1 end
		if v == "op" and cap[i] then opcap[cap[i]] = (opcap[cap[i]] or 0) + 1 end
		if v == "dc" and cap[i] then dccap[cap[i]] = (dccap[cap[i]] or 0) + 1 end
	end
	-- construct html strings from the sets of capacities
	-- first make a sequential table
	-- under construction
	local uccapseq = {}
	for k, v in pairs(uccap) do
		uccapseq[#uccapseq+1] = v .. " x " .. k
	end
	table.sort(uccapseq, numcomp2)
	if psu_uc == "" then psu_uc = table.concat(uccapseq, "<br>") end
	-- operational
	local opcapseq = {}
	for k, v in pairs(opcap) do
		opcapseq[#opcapseq+1] = v .. " x " .. k
	end
	table.sort(opcapseq, numcomp2)
	if psu_op == "" then psu_op = table.concat(opcapseq, "<br>") end
	-- decommissioned
	local dccapseq = {}
	for k, v in pairs(dccap) do
		dccapseq[#dccapseq+1] = v .. " x " .. k
	end
	table.sort(dccapseq, numcomp2)
	if psu_dc == "" then psu_dc = table.concat(dccapseq, "<br>") end

	-- construct table rows
	local out = ""
	if psu_op ~= "" then
		out = out ..  "<tr><th style='width:10em;'>" .. i18n.op_lbl
		.. "</th><td>" .. psu_op .. "</td></tr>"
	end
	if psu_mm ~= "" then
		out = out ..  "<tr><th style='width:10em;'>" .. i18n.mm_lbl
		.. "</th><td>" .. psu_mm .. "</td></tr>"
	end
	if psu_uc ~= "" then
		out = out ..  "<tr><th style='width:10em;'>" .. i18n.uc_lbl
		.. "</th><td>" .. psu_uc .. "</td></tr>"
	end
	if psu_dc ~= "" then
		out = out ..  "<tr><th style='width:10em;'>" .. i18n.dc_lbl
		.. "</th><td>" .. psu_dc .. "</td></tr>"
	end

	--[[ debug
	local debugstr = "debug info<br>"
	for i, v in pairs(status) do
		debugstr = debugstr .. i .. " - " .. v .. " - " .. (cap[i] or "") .. " - " .. (mm[i] or "") .. "<br>"
	end

	local count = 0
	for k, v in pairs(opmm) do
		count = count +1
	end

	debugstr = debugstr:sub(1, -5) .. "<br>opmm size = " ..count
	out = out  ..  "<tr><td colspan='2'>" .. debugstr .. "</td></tr>"
	--]]

	-- construct table
	out = "<table>" .. out .. "</table>"

	return out
end

return p