Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus


local p = {}
	
	-- require all country-related functions and data
	local countryfunctions = require ("Module:Musikcharts/countries")
	-- require formatted certification icons
	local certicon = require ("Module:Musikcharts/certifications")
	-- require local labels
	local label = require ("Module:Musikcharts/locallabels")
	-- require local parameter names
	local param = require ("Module:Musikcharts/localparameters")
	-- require local css classes
	local cssclass = require ("Module:Musikcharts/localclasses")
	
	-- require date-related functions
	local luckier, DateTime = pcall( require, "Module:DateTime" )
	if type( DateTime ) == "table" then
    	DateTime = DateTime.DateTime()
	else
    	-- DateTime contains error
    	return "<span class='error'>" .. DateTime .. "</span>"
	end
	
	-- require parameter check
	local lucky, TemplatePar = pcall( require, "Modul:TemplatePar" )
	if type( TemplatePar ) == "table" then
	    TemplatePar = TemplatePar.TemplatePar()
	else
	    -- TemplatePar contains error
	    return "<span class='error'>" .. TemplatePar .. "</span>"
	end
	
	local templatestyles = "Vorlage:Charttabelle/styles.css"


-- Charttabelle - chart table
p.charttablehead = function (frame, christmas)
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- service links
	local slnosources = "<span style='display:none'>[[Template:Charttabelle/Wartung/ohne Quellen]]</span>"
	local sltoomanycountries = "<span style='display:none'>[[Template:Charttabelle/Wartung/zu viele Länder]]</span>"
	local slwrongrformat = "<span style='display:none'>[[Template:Charttabelle/Wartung/falsche Art]]</span>"
	local slmonths = "<span style='display:none'>[[Template:Charttabelle/Wartung/Monatsdaten]]</span>"
	local slchartsnonexist = "<span style='display:none'>[[Template:Charttabelle/Wartung/Charts inexistent]]</span>"
	local slparameterissue = "<span style='display:none'>[[Template:Charttabelle/Wartung/Parameterfehler]]</span>"
	-- /
	
	-- get countries
	local countries = {}
	local i = 0
	for k, v in ipairs (parameters) do
		v = mw.text.trim( v )
		if #v > 0 then
			i = i + 1
			countries[i] = v
		end
	end
	
	if #countries > 8 then return "<span class='error'>Charttabelle: Zu viele Länder definiert!</span>" .. sltoomanycountries end
	-- /
	
	-- direct template parameters
	local source				= parameters[param.sources]
	if source then
		source = mw.text.trim (source)
			:gsub ("\n", "")
	end
	local rformat				= parameters[param.rformat]
	local sortable				= parameters[param.sortable]
	local grey					= parameters[param.grey]
	local extra 				= parameters[param.extra]
	local titleaddition 		= parameters[param.titleadd]
	local givenwidth			= parameters[param.width]
	local content				= parameters[param.content] or ""
	-- /
	
	-- headers
	local headerclass			= cssclass.headerrow
	local mobheaderclass		= cssclass.headercell
	if grey then
		headerclass 			= cssclass.headerrowgrey
		mobheaderclass			= cssclass.headercellgrey
	end
	-- /
	
	-- parameter check
	local templatename
	if christmas then
		templatename			= "[[Vorlage:Weihnachtscharttabelle|Weihnachtscharttabelle]]"
	else
		templatename			= "[[Vorlage:Charttabelle|Charttabelle]]"
	end
	local parametercheck = {
		["mandatory"]			= {param.content, "1"},
		["optional"]			= {param.sources, param.rformat, param.sortable, param.grey, "2", "3", "4", "5", "6", "7", "8"},
		["template"]			= templatename
	}
	if not christmas then
		table.insert (parametercheck["optional"], param.extra)
		table.insert (parametercheck["optional"], param.titleadd)
		table.insert (parametercheck["optional"], param.width)
	end
	local parameterissue		= TemplatePar.check(parametercheck)
	-- /
	
	-- table width
	local tablewidth = {
		["1"]  = { "250", "320" },
		["1e"] = { "245", "220", "175" },
		["2"]  = { "300", "320" },
		["2e"] = { "285", "220", "175" },
		["3"]  = { "350", "300" },
		["3e"] = { "315", "210", "160" },
		["4"]  = { "400", "270" },
		["4e"] = { "345", "200", "160" }
	}
	local width = "1" -- default width
	local colnumber = 1 + #countries
	if not christmas then
		colnumber = colnumber + 2
	end
	if tablewidth[givenwidth] then
		width = givenwidth
	end
	if extra then
		width = width .. "e"
		colnumber = colnumber + 1
	end
	-- /
	
	-- test for monthly chart data
	local months
	if string.match (content, "Mt%.%)") then
		months = true
	end
	-- /
	
	-- check number of rows
	local rownumber
	content, rownumber = string.gsub (content, "class='newcharttablerow' ", "")
	-- /
	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	
	-- parameter check error
	if parameterissue then
		ret = ret .. "\n" .. parameterissue .. slparameterissue
	end
	-- /
	
	-- start building table
	ret = ret .. "\n{| class='wikitable charts-table"
	if sortable then
		ret = ret .. " sortable"
	end
	if rownumber > 8 then
		ret = ret .. " charts-stickyhead"
	end
	if grey then
		ret = ret .. " charts-zebra"
	else
		ret = ret .. " charts-zebragrey"
	end
	if christmas then
		ret = ret .. " charts-xmas"
	end
	ret = ret .. "' style='text-align:center;"
	ret = ret .. "'\n|-\n! style='width:25px;' class='" .. mobheaderclass .. " " .. headerclass .. "' rowspan='2' | "
	if christmas then
		ret = ret .. "Periode"
	else
		ret = ret .. "Jahr"
		ret = ret .. "\n! style='width:" .. tablewidth[width][1] .. "px;' class='" .. mobheaderclass .. " " .. headerclass .. "' rowspan='2'| Titel"
		if titleaddition then
			ret = ret .. "<br /><span style='font-size:smaller;font-style:italic;'>" .. titleaddition .. "</span>"
		elseif rformat == "Singles" then
			ret = ret .. "<br /><span style='font-size:smaller;font-style:italic;'>Album</span>"
		end
	end
	ret = ret .. "\n! class='" .. mobheaderclass .. "' colspan='" .. #countries .. "'| "
	ret = ret .. "<span style='white-space:nowrap;'><span class='charts-hidm charts-certc'><span class='charts-certt'>Höchstplatzierung, Gesamtwochen"
	if months then
		ret = ret .. "/&#8203;&#8209;monate" -- zero-width space + nonbreaking hyphen
	end
	if not christmas then
		ret = ret .. ", Auszeichnung"
	end
	ret = ret .. "<i></i></span>"
	if #countries > 1 then
		ret = ret .. "Chartplatzierungen"
	else
		ret = ret .. "Charts"
	end
	ret = ret .. "</span><span class='charts-monl'>Chartplatzierungen</span>"
	
	-- sources
	ret = ret .. (source or slnosources) .. "</span>"
	-- /
	
	-- insert service links
	if rformat then
		if not rformat == "" and not rformat == "Singles" and not rformat == "Alben" then
			ret = ret .. slwrongrformat
		end
	end
	if months then
		ret = ret .. slmonths
	end
	-- /
	
	-- mobile header
	ret = ret .. "<span class='charts-monl charts-mh'><br />"
	if christmas then
		ret = ret .. "(Periode, "
	else
		ret = ret .. "(Jahr, Titel, "
		if titleaddition then
			if string.match (titleaddition, "<br") then
				titleaddition = string.gsub (titleaddition, "%s?<br%s?/?>%s?", " / ")
			end
			if string.match (titleaddition, "%(") then
				titleaddition = titleaddition
					:gsub ("%(", "[")
					:gsub ("%)", "]")
			end
			ret = ret .. "<i>" .. titleaddition .. "</i>, "
		elseif rformat == "Singles" then
			ret = ret .. "<i>Album</i>, "
		end
	end
	ret = ret .. "Plat&shy;zie&shy;rungen, Wo&shy;chen"
	if months then
		ret = ret .. "/Mo&shy;nate"
	end
	if not christmas then
		ret = ret .. ", Aus&shy;zeich&shy;nungen, Anmer&shy;kungen"
		if extra then
			local mobileextra = extra
			if string.match (mobileextra, "<br") then
				mobileextra = string.gsub (mobileextra, "%s?<br%s?/?>%s?", " / ")
			end
			if string.match (mobileextra, "%(") then
				mobileextra = mobileextra
					:gsub ("%(", "[")
					:gsub ("%)", "]")
			end
			ret = ret .. ", " .. mobileextra
		end
	end
	ret = ret .. ")</span>"
	-- /

	if not christmas then
		ret = ret .. "\n! style='width:" .. tablewidth[width][2] .. "px;' class='" .. mobheaderclass .. " " .. headerclass
		if sortable then
			ret = ret .. " unsortable"
		end
		ret = ret .. "' rowspan='2' | Anmerkungen"
		if extra then
			ret = ret .. "\n! style='width:" .. tablewidth[width][3] .. "px;' rowspan='2' class='"
			if sortable then
				ret = ret .. "unsortable "
			end
			ret = ret .. mobheaderclass .. " " .. headerclass .. "' |" .. extra
		end
	end
	
	-- mobile header for colspans/rowspans
	if string.match (content, "class%='charts%-monla'") then
		ret = ret .. "\n! style='font-style:italic;border:none;margin-top:-1px;' class='charts-monlc charts-mh' |" .. "[&uarr;]: gemeinsam behandelt mit vorhergehendem Eintrag;<br />[&larr;]: in beiden Charts platziert"
	end
	-- /
	
	-- country columns
	ret = ret .. "\n|- class='" .. headerclass .. "'"
	ret = ret .. countryfunctions.countryhead( {countries = countries}, rformat, sortable, grey )
	
	-- / end of table
	
	-- content substitutions
	for c = 1, #countries do
		local country = countries[c]
		
		-- correct no1 links for US R&B and Country singles
		if rformat == "Singles" then
			if country == "US-RB" then
				content = string.gsub (content, "%[%[Liste der Nummer%-eins%-R&B%-Alben in den USA %(%d%d%d%d%)|<b>1</b>]]<!%-%-Albumcharts%-%->", "<b>1</b>")
			elseif country == "US-C" then
				content = string.gsub (content, "%[%[Liste der Nummer%-eins%-Country%-Alben in den USA %(%d%d%d%d%)|<b>1</b>]]<!%-%-Albumcharts%-%->", "<b>1</b>")
			end
		end
		-- /
		
		-- link individual country names in mobile countrydisplay
		country = country:gsub("</?small>", ""):gsub("%[%[Datei:.-]]", "")
		if string.match (country, "]]") then
			local indivcountry, indivcountrysuffix = string.match (country, "%[%[(.+)]](.*)")
	--		if string.match (indivcountry, "<br\s?/?>") then
	--			indivcountry, indivcountrysuffix = string.match (indivcountry, "(.+)<br\s?/?>(.+)")
	--		end
			if string.match (indivcountry, "%[%[") then
				indivcountry = string.match (indivcountry, "%[%[(.+)")
			end
			if indivcountrysuffix == ")" then indivcountrysuffix = "" end
			local indivcountrynolink = string.match (indivcountry, "|(.+)") or ""
			
			local indivcountrymatch = "<span class='indivcountry" .. c .. "'>.-</span>"
			local indivcountrynolinkmatch = "<span class='indivcountrynolink" .. c .. "'>.-</span>"
			
			content = content
				:gsub (indivcountrymatch, "[[" .. indivcountry .. "]]" .. indivcountrysuffix)
				:gsub (indivcountrynolinkmatch, indivcountrynolink .. indivcountrysuffix)
		end
		-- /
	end

	-- correct chart links for singles in mobile countrydisplay
	if rformat == "Singles" then
		content = countryfunctions.singlechartlink (content)
	end
	
	-- correct marking of non-existing charts
	if string.match (content, "charts%-nxa") or string.match (content, "charts%-nxs") then
		if rformat == "Singles" then
			content = content
				:gsub ("charts%-nxa", "")
				:gsub ("<!%-%- Albumcharts inexistent %-%->", "")
		else
			content = content
				:gsub ("charts%-nxs", "")
				:gsub ("<!%-%- Singlecharts inexistent %-%->", "")
		end
		if string.match (content, "<!%-%- Albumcharts inexistent %-%->") then
			content = string.gsub (content, "<!%-%- Albumcharts inexistent %-%->", "")
			ret = ret .. slchartsnonexist
		end
		if string.match (content, "<!%-%- Singlecharts inexistent %-%->") then
			content = string.gsub (content, "<!%-%- Singlecharts inexistent %-%->", "")
			ret = ret .. slchartsnonexist
		end
	end
	
	-- correct colours for grey styles
	if grey then
		content = content
			:gsub ("charts%-redst", "charts-redstg")
			:gsub ("charts%-mc'", "charts-mcg'")
			:gsub (" charts%-yelst", "")
	end
	-- /
	
	-- delete empty class arguments and single row/colspans
	content = content
		:gsub (" class=''", "")
		:gsub (" rowspan='1'", "")
		:gsub (" colspan='1'", "")
	-- /
	
	-- correct full-width colspans
	if colnumber ~= 12 then -- Charthinweis
		content = content
			:gsub ('colspan="12"', 'colspan="' .. colnumber .. '"')
			:gsub ("colspan='12'", "colspan='" .. colnumber .. "'")
	end
	if not extra then -- Chartauswertung
		content = content
			:gsub ("rowspan='3' colspan='2'", "rowspan='3'")
	end
	-- /
	
	-- delete unused sortkeys
	if not sortable then
		content = content
			:gsub ("data%-sort%-value='.-'", "")
		end
	-- /
	
	-- better explain colspans in mobile view
	local function replacer(text)
		return (string.gsub (text, "(\n|.-colspan=.-|.-<span class='charts%-monl.-<span.-class='charts%-)monla'>%[(.-)&uarr;(%]</span>)", "%1monl' style='font-size:smaller;font-style:italic;'> %[%2&larr;%3"))
	end
	if string.match (content, "&uarr;%]") then
		content = string.gsub (content, "\n|[^\n]*charts%-monl[^\n]*<span[^\n]*charts%-monla[^\n]*", replacer)
	end
		-- visibility in hidden cells
		content = string.gsub (content, "(\n|[^\n]*)charts%-hidm([^\n]*)' | &mdash;([^\n]*<span[^\n]*charts%-monla)", "%1charts-aup%2' | <span class='charts-hidm'>&mdash;</span>%3")
	-- /

	ret = ret .. "\n|- \n" .. content .. "\n|- \n|}"
	
	-- add explanation for non-existing charts
	if string.match (content, "charts%-nxa") or string.match (content, "charts%-nxs") then
		ret = ret .. "<span style='font-size:smaller;' class='charts-hidm charts-hidp'><span class='charts-nxa' style='padding:2px;border:solid .5px grey;font-style:italic;'>grau schraffiert</span>: keine Chartdaten aus diesem Jahr verfügbar</span>"
	end
	-- /

	return frame:preprocess (ret)
end



-- Chartauswertung - chart statistics
p.chartstatistics = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- service links
	local sltoomanycountries = "<span style='display:none'>[[Template:Charttabelle/Wartung/zu viele Länder]]</span>"
	local slwrongrformat = "<span style='display:none'>[[Template:Charttabelle/Wartung/falsche Art]]</span>"
	local slparameterissue = "<span style='display:none'>[[Template:Charttabelle/Wartung/Parameterfehler]]</span>"
	-- /
	
	-- get countries
	local countries = {}
	local i = 0
	for k, v in ipairs (parameters) do
		v = mw.text.trim( v )
		if #v > 0 then
			i = i + 1
			countries[i] = v
		end
	end
	
	if #countries > 8 then return "|-\n| colspan='12' | <span class='error'>Chartauswertung: Zu viele Länder definiert!</span>" .. sltoomanycountries end
	-- /
	
	-- direct template parameters
	local rformat = parameters[param.rformat]
	local comment = parameters[param.comment]
	local istable = parameters[param.istable]
	local grey = parameters[param.grey]
	-- /
	
	local greycountry
	if grey then
		greycountry = "g"
	else
		greycountry = ""
	end
	
	-- parameter check
	local parametercheck = {
		["mandatory"] = { "1" },
		["optional"] = { param.rformat, param.comment, param.extra, param.istable, param.grey, "2", "3", "4", "5", "6", "7", "8" },
		["template"] = "Chartauswertung"
	}
	-- /
	
	-- start building table
	local ret
	if istable then
		ret = "{| class='wikitable charts-table"
		if grey then
			ret = ret .. " charts-zebra"
		else
			ret = ret .. " charts-zebragrey2"
		end
		ret = ret .. "' style='text-align:center;break-inside:avoid;'\n |- class='"
		if grey then
			ret = ret .. "charts-trhg"
		else
			ret = ret .. "charts-trh"
		end
		ret = ret .. "' \n ! style='width:200px;'"
		if grey then
			ret = ret .. " class='charts-thg' |"
		else
			ret = ret .. " class='charts-th' |"
		end
		
		-- country columns
		ret = ret .. countryfunctions.countryhead( {countries = countries }, rformat, nil, grey )
		-- /
		
		ret = ret .. "\n|- style='border-top:none;'"
	else
		ret = "|- class='sortbottom charts-redst'\n| class='charts-hidm' rowspan='3'|"
	end

	ret = ret .. "\n| style='text-align:left;'"
	if istable then
		ret = ret .. " class='charts-sth" .. greycountry .. "'"
	end
	ret = ret .. " |"
	if rformat then
		ret = ret .. "Nummer-eins-" .. rformat
	else
		ret = ret .. "Nummer eins"
	end
	for c = 1, #countries do
		local country = countries[c]
		local n = param.no1 .. "_" .. country
		table.insert (parametercheck["optional"], n)
		local No1 = parameters[n]
		if No1 == "" or No1 == nil then
			No1 = "&mdash;"
		end
		
		-- mobile country display
		ret = ret .. "\n| "
		if No1 == "&mdash;" and not istable then
			ret = ret .. "class='charts-hidm' | "
		end
		ret = ret .. "<span class='charts-mc" .. greycountry .. "'>" .. countryfunctions.countrycol (country, c, nil, nil, rformat) .. "</span>"
		-- /
		
		ret = ret .. No1
		
		-- mobile country display width balance
		ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true, nil, rformat) .. "</span>"
		-- /
	end

	if not istable then
		ret = ret .. "\n| rowspan='3' colspan='2' style='text-align:left; font-size:smaller;' "
		if comment then
			ret = ret .. "| " .. comment
		else
			ret = ret .. "class='charts-hidm' |"
		end
	end

	ret = ret .. "\n|- "
	if not istable then
		ret = ret .. "class='sortbottom charts-redst' "
	end
	ret = ret .. "\n| style='text-align:left;'"
	if istable then
		ret = ret .. " class='charts-sth" .. greycountry .. "'"
	end
	ret = ret .. " |"
	if rformat then
		ret = ret .. "Top-10-" .. rformat
	else
		ret = ret .. "in den Top 10"
	end
	for c = 1, #countries do
		local country = countries[c]
		local t = param.t10 .. "_" .. country
		table.insert (parametercheck["optional"], t)
		local Top10 = parameters[t]
		if Top10 == "" or Top10 == nil then
			Top10 = "&mdash;"
		end
		ret = ret .. "\n| "
		if Top10 == "&mdash;" and not istable then
			ret = ret .. "class='charts-hidm' | "
		end
		
		-- mobile country display
		ret = ret .. "<span class='charts-mc" .. greycountry .. "'>" .. countryfunctions.countrycol (country, c) .. "</span>"
		-- /
		
		ret = ret .. Top10
		
		-- mobile country display width balance
		ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true) .. "</span>"
		-- /
	end

	ret = ret .. "\n|- "
	if istable then
		ret = ret .. "style='font-weight:bold;'"
		if not grey then ret = ret .. " class='charts-yelst'" end
	else
		ret = ret .. "class='sortbottom charts-redst'"
	end
	ret = ret .. "\n| style='text-align:left;'"
	if istable then
		ret = ret .. " class='charts-sth" .. greycountry .. "'"
	end
	ret = ret .. " |" .. ((rformat .. " ") or "") .. "in den Charts"
	for c = 1, #countries do
		local country = countries[c]
		local g = param.tot .. "_" .. country
		table.insert (parametercheck["optional"], g)
		local Total = parameters[g]
		if Total == "" or Total == nil then
			Total = "&mdash;"
		end
		ret = ret .. "\n| "
		if Total == "&mdash;" and not istable then
			ret = ret .. "class='charts-hidm' | "
		end
		
		-- mobile country display
		ret = ret .. "<span class='charts-mc" .. greycountry .. "'>" .. countryfunctions.countrycol (country, c) .. "</span>"
		-- /
		
		ret = ret .. Total
		
		-- mobile country display width balance
		ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true) .. "</span>"
		-- /
	end
	
	-- insert service links
	if rformat then
		if not rformat == "" and not rformat == "Singles" and not rformat == "Alben" then
			ret = ret .. slwrongrformat
		end
	end
	-- /

	if istable then
		ret = ret .. "\n|}"
	end
	
	-- parameter check error
	local parameterissue = TemplatePar.check(parametercheck)
	if parameterissue then
		if not istable then 
			ret = ret .. "\n|-\n| colspan='12' class='charts-redst' | " 
		else 
			ret = ret .. "\n" 
		end
		ret = ret .. parameterissue .. slparameterissue
	end
	-- /

	return frame:preprocess (ret)
end



-- Weihnachtscharttabelle - x-mas chart table
p.xcharttablehead = function (frame)
	
	return p.charttablehead (frame, true)
end



-- Charteintrag - chart table entry
p.charttablerow = function (frame, christmas)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- get countries
	local countries = {}
	local i = 0
	for k, v in ipairs (parameters) do
		v = mw.text.trim( v )
		if #v > 0 then
			i = i + 1
			countries[i] = v
		end
	end
	-- /
	
	-- direct template parameters and x-mas distinction
	local year
	if christmas then
		year = parameters[param.period]
	else
		year = parameters[param.year]
	end
	local colour = parameters[param.colour]
	local unnumberedtitle
	if christmas then
		unnumberedtitle = "title"
	else
		unnumberedtitle = parameters[param.title]
	end
	-- /
	
	-- parameter check
	local templatename
	if christmas then
		templatename = "[[Vorlage:Weihnachtscharteintrag|Weihnachtscharteintrag]]"
	else
		templatename = "[[Vorlage:Charteintrag|Charteintrag]]"
	end
	local parametercheck = {
		["mandatory"] = { "1" },
		["optional"] = { "2", "3", "4", "5", "6", "7", "8" },
		["template"] = templatename
	}
	if christmas then
		table.insert (parametercheck["optional"], param.period)
	else
		table.insert (parametercheck["optional"], param.year)
	end
	-- /
	
	-- row numbering
	if unnumberedtitle then
		parameters[param.colour .. "1"] = parameters[param.colour]
		table.insert (parametercheck["optional"], param.colour)
		parameters[param.title .. "1"] = unnumberedtitle
		parameters[param.album .. "1"] = parameters[param.album]
		parameters[param.titleadd .. "1"] = parameters[param.titleadd]
		for c = 1, #countries do
			local ps = param.position .. "_" .. countries[c]
			table.insert (parametercheck["optional"], ps)
			local ps1 = param.position .. "_" .. countries[c] .. "1"
			parameters[ps1] = parameters[ps]
			local w = param.weeks .. "_" .. countries[c]
			table.insert (parametercheck["optional"], w)
			local w1 = param.weeks .. "_" .. countries[c] .. "1"
			parameters[w1] = parameters[w]
			local m = param.months .. "_" .. countries[c]
			table.insert (parametercheck["optional"], m)
			local m1 = param.months .. "_" .. countries[c] .. "1"
			parameters[m1] = parameters[m]
			local y = param.year .. "_" .. countries[c]
			table.insert (parametercheck["optional"], y)
			local y1 = param.year .. "_" .. countries[c] .. "1"
			parameters[y1] = parameters[y]
			local s = param.columns .. "_" .. countries[c]
			table.insert (parametercheck["optional"], s)
			local s1 = param.columns .. "_" .. countries[c] .. "1"
			parameters[s1] = parameters[s]
			local z = param.rows .. "_" .. countries[c]
			table.insert (parametercheck["optional"], z)
			local z1 = param.rows .. "_" .. countries[c] .. "1"
			parameters[z1] = parameters[z]
			local a = param.certification .. "_" .. countries[c]
			table.insert (parametercheck["optional"], a)
			local a1 = param.certification .. "_" .. countries[c] .. "1"
			parameters[a1] = parameters[a]
		end
		parameters[param.comment .. "1"] = parameters[param.comment]
		parameters[param.extra .. "1"] = parameters[param.extra]
		parameters[param.rows .. "_" .. param.extra .. "1"] = parameters[param.rows .. "_" .. param.extra]
		if not christmas then
			table.insert (parametercheck["optional"], param.title)
			table.insert (parametercheck["optional"], param.album)
			table.insert (parametercheck["optional"], param.titleadd)
			table.insert (parametercheck["optional"], param.comment)
			table.insert (parametercheck["optional"], param.extra)
			table.insert (parametercheck["optional"], "Zeilen_Extra")
		end
	end
	local rows = 0
	repeat
		rows = rows + 1
		local title = param.title .. rows
	until not parameters[title]
	rows = rows - 1
	-- /
	
	-- service links
	local sltoomanycountries = "<span style='display:none'>[[Template:Charttabelle/Wartung/zu viele Länder]]</span>"
	local slmissingtitle = "<span style='display:none'>[[Template:Charttabelle/Wartung/Titel fehlt]]</span>"
	local slwrongyear = "<span style='display:none'>[[Template:Charttabelle/Wartung/Jahr]]</span>"
	local slparameterissue = "<span style='display:none'>[[Template:Charttabelle/Wartung/Parameterfehler]]</span>"
	local sltemporary = "<span style='display:none'>[[Template:Charttabelle/Wartung/vorläufig"
	if year then
		if string.match(year, "^%d%d%d%d") then
			if tonumber(string.match(year, "^(%d%d%d%d)")) > 2009 then
				sltemporary = sltemporary .. "/" .. string.match(year, "^(%d%d%d%d)")
			end
		end
	end
	sltemporary = sltemporary .. "]]</span>"
	local slbelgiumold = "<span style='display:none'>[[Template:Charttabelle/Wartung/Belgien vor 1995]]</span>"
	
	if #countries > 8 then 
		return "|-\n| colspan='12' | <span class='error'>" .. (year or "Charteintrag") .. ": Zu viele Länder definiert!</span>" .. sltoomanycountries
	end
	if rows == 0 then 
		return "|-\n| colspan='12' | <span class='error'>" .. (year or "Charteintrag") .. ": Charteinträge nicht dargestellt, 'Titel'/'Titel1' fehlt!</span>" .. slmissingtitle
	end
	-- /

	-- start building table
	local ret = "|- "
	-- fallback for row colours, overwriting CSS zebra style (first row)
	if christmas and year == "Insgesamt" then
		ret = ret .. " rowspan='" .. rows .. "' class='sortbottom charts-yelst' \n| style='font-style:italic;' | " .. year
	else
		if colour == "1" then
			ret = ret .. " class='charts-grey'"
		elseif colour == "0" then
			ret = ret .. " class='charts-blue'"
		end
		ret = ret .. "\n | rowspan='" .. rows .. "' class='charts-yy' | " .. (year or "")
	end

	if year then
		if christmas then
			if not string.match (year, "^%d%d%d%d") and year ~= "Insgesamt" then
				ret = ret .. slwrongyear
			end
		else
			if not string.match (year, "^%d%d%d%d$") then
				ret = ret .. slwrongyear
			end
		end
	else
		ret = ret .. slwrongyear
	end

	for row = 1, rows do
		local t = param.title .. row
		local title = parameters[t]
		local a = param.album .. row
		local album = parameters[a]
		local ta = param.titleadd .. row
		local titleaddition = parameters[ta]
		local co = param.colour .. row
		local rowcolour = parameters[co]
		if row > 1 then
			ret = ret .. "\n|- "
		-- individual row colours, overwriting everything
			if rowcolour == "1" then
				ret = ret .. " class='charts-grey'"
				else
					if rowcolour == "0" then
						ret = ret .. " class='charts-blue'"
						else
		-- fallback for row colours, overwriting CSS zebra style (other rows)
							-- check if even
							if row % 2 == 0 then
								if colour == "0" then
									ret = ret .. " class='charts-grey'"
								elseif colour == "1" then
									ret = ret .. " class='charts-blue'"
								end
							-- if odd
							else
								if colour == "0" then
									ret = ret .. " class='charts-blue'"
								elseif colour == "1" then
									ret = ret .. " class='charts-grey'"
								end
							end
					end
			end
		end
		if not christmas then
			table.insert (parametercheck["optional"], t)
			table.insert (parametercheck["optional"], a)
			table.insert (parametercheck["optional"], ta)
			table.insert (parametercheck["optional"], co)
			ret = ret .. "\n| class='newcharttablerow' | " .. title -- class newcharttablerow for row count in charttable
			if album or titleaddition then
				ret = ret .. "<br /><span "
				if not (album == "–" or titleaddition == "–") then
					ret = ret .. "class='charts-add'"
				else
					ret = ret .. "style='font-size:smaller;'"
				end
				ret = ret .. ">" .. (album or titleaddition) .. "</span>"
			end
		end

		for c = 1, #countries do
			local country = countries[c]
			local ps = param.position .. "_" .. country .. row
			table.insert (parametercheck["optional"], ps)
			local position = parameters[ps]
			local w = param.weeks .. "_" .. country .. row
			table.insert (parametercheck["optional"], w)
			local weeks = parameters[w]
			local m = param.months .. "_" .. country .. row
			table.insert (parametercheck["optional"], m)
			local months = parameters[m]
			local y = param.year .. "_" .. country .. row
			table.insert (parametercheck["optional"], y)
			local year1 = parameters[y]
			local s = param.columns .. "_" .. country .. row
			table.insert (parametercheck["optional"], s)
			if parameters[s] and #parameters[s] == 0 then parameters[s] = nil end
			local z = param.rows .. "_" .. country .. row
			table.insert (parametercheck["optional"], z)
			if parameters[z] and #parameters[z] == 0 then parameters[z] = nil end
			local a = param.certification .. "_" .. country .. row
			table.insert (parametercheck["optional"], a)
			local certification = parameters[a]
			local certref
			if certification then
				if string.match (certification, "ref") then
					certref = string.match (certification, "[%a%d%s%+%(%)]*(.+)")
				end
			end
			
			-- variables for tracking of non-existing charts
			local slchartnonexacheck
			local slchartnonexa = "<!-- Albumcharts inexistent -->"
			local slchartnonexscheck
			local slchartnonexs = "<!-- Singlecharts inexistent -->"
			-- /

			if position ~= "n" then
				ret = ret .. "\n|"
				
				-- give position as sortkey
				local sortpos
				if not position or position == "" then
					sortpos = "300!"
				else
					local nude = mw.text.unstrip( position )
					sortpos = string.match (nude, "(%d+)") or "300!"
				end
				ret = ret .. " data-sort-value='" .. sortpos .. "'"
				-- /
				
				-- classes
				ret = ret .. " class='"
				
				-- mobile hiding of empty cells
				if not position or position == "" then
					if not certification then
						ret = ret .. "charts-hidm"
					end
				end
				-- /
				
				-- mark non-existing chart years
				if not countryfunctions.chartexist (country, "Alben", year) then
					ret = ret .. " charts-nxa"
					slchartnonexacheck = true
				end
				if not countryfunctions.chartexist (country, "Singles", year) then
					ret = ret .. " charts-nxs"
					slchartnonexscheck = true
				end
				-- /
				
				ret = ret .. "'"
				-- / close classes
				
				-- define colspan and/or rowspan
				if parameters[s] then
					ret = ret .. " colspan='" .. parameters[s] .. "'"
				end
				if parameters[z] then
					ret = ret .. " rowspan='" .. parameters[z] .. "'"
				end
				-- /

				ret = ret .. " | "
				
				-- mobile country display
				local mobiledisplay
				if position or certification then
					mobiledisplay = true
					ret = ret .. "<span class='charts-mc'>" .. countryfunctions.countrycol (country, c) .. "</span>"
				end
				-- /

				if certification then
					certification = " " .. certicon.certicon(frame, certification)
					certification = certification .. (certref or "")
				else
					certification = ""
				end
				
				if position then
					-- create links to lists of number-one hits in selected countries
					if position == "1" or string.match(position, "^1%D") then
						position = countryfunctions.numberonelinks (position, country, (year1 or year))
					end
					-- /
					
					if position == "" then
						ret = ret .. "&mdash;" .. certification
					else
						if weeks then
							if weeks == "n" then
								ret = ret .. position .. certification
							else
								if weeks == "" then
									ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(&hellip; Wo.)</span>" .. sltemporary
								else
									ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(" .. weeks .. " Wo.)</span>"
								end
							end
						else
							if months then
								if months == "n" then
									ret = ret .. position .. certification
								else
									if months == "" then
										ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(&hellip; Mt.)</span>" .. sltemporary
									else
										ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(" .. months .. " Mt.)</span>"
									end
								end
							else -- default is weeks
								if position then
									ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(&hellip; Wo.)</span>" .. sltemporary
								end
							end
						end
						-- service links for given position in non-existing charts
						if slchartnonexacheck then
							ret = ret .. slchartnonexa
						end
						if slchartnonexscheck then
							ret = ret .. slchartnonexs
						end
						-- /
						-- service link for pre-1995 Belgium data
						if country == "BE" or country == "BEF" or country == "BEW" then
							if (tonumber(year) or 0) < 1995 then
								ret = ret .. slbelgiumold
							end
						end
						--/
					end
				else --: if not position
					ret = ret .. "&mdash;" .. certification
				end

				-- mobile country display width balance
				if mobiledisplay then
					ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true) .. "</span>"
				end
				-- /
				
			else --: position == "n"
				ret = ret .. "<span class='charts-monla'>[" .. (countryfunctions.countrycol (country, c, true) or country or "") .. ":&nbsp;&uarr;]</span>"
			end
		end
		
		-- final table columns
		if not christmas then
			local com = param.comment .. row
			table.insert (parametercheck["optional"], com)
			local comment = parameters[com]
			ret = ret .. "\n| class='charts-cm' "
			if comment and comment ~= "" then
				ret = ret .. "| <div>\n" .. comment .. "</div>"
			else
				ret = ret .. "class='charts-hidm' |"
			end
			local x = param.extra .. row
			table.insert (parametercheck["optional"], x)
			local extra = parameters[x]
			local zx = param.rows .. "_" .. param.extra .. row
			table.insert (parametercheck["optional"], zx)
			if extra then
				if parameters[zx] then
					ret = ret .. "\n| rowspan='" .. parameters[zx] .. "' | " .. extra
				else
					ret = ret .. "\n| " .. (extra or "")
				end
			end
		end
	end

	-- parameter check error
	local parameterissue = TemplatePar.check(parametercheck)
	if parameterissue then
		ret = ret .. "\n|-\n| colspan='12' | " .. parameterissue .. slparameterissue
	end
	-- /

	return ret
end



-- Weihnachtscharteintrag - x-mas chart table row
p.xcharttablerow = function (frame)
	
	return p.charttablerow (frame, true)
end



-- Chartplatzierungen - chart positions table
p.chartposhead = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- get content and define rows
	local entry = {}
	for k, v in ipairs (parameters) do
		entry [k] = v
	end
	local rows = 0
	repeat
		rows = rows + 1
		local entry = "" .. rows
	until not parameters[entry]
	rows = rows - 1
	-- /
	
	-- direct template parameters
	local title		= parameters[param.title]
	local year		= parameters[param.year]
	local source	= parameters[param.source]
	local grey		= parameters[param.grey]
	-- /
	
	-- derived parameters
	local months
	local weeks = true
	local monthscount = 0
	for searchrow = 1, rows do
		if string.match (entry[searchrow], "&nbsp;" .. label.mt) then
			months = true
			monthscount = monthscount + 1
		end
	end
	if monthscount == rows then
		weeks = false
	end
	local tablecaption = title
	if title == label.chartpositions:gsub("&shy;", "") or title == label.yearendcharts:gsub("&shy;", "") then -- avoid duplicating default title
		tablecaption = mw.html.create ("span")
						:addClass(cssclass.hidemobile)
						:wikitext(title)
	end
	local weeksmonths
	if weeks then
		weeksmonths = label.weeks
		if months then
			weeksmonths = weeksmonths .. "/<br />" .. label.months
		end
	else
		weeksmonths = label.months
	end
	local tableheaderfirstyear = label.chartpositions
	local yeardisplay
	if year then
		tableheaderfirstyear = label.yearendcharts
		yeardisplay = " (" .. year .. ")"
	end
	-- /
	
	-- CSS classes
	local headerclass		= cssclass.headerrow
	local mobheaderclass	= cssclass.headercell
	local zebraclass		= cssclass.zebra2
	if grey then
		headerclass 		= cssclass.headerrowgrey
		mobheaderclass		= cssclass.headercellgrey
		zebraclass			= cssclass.zebraclassic
	end
	local stickyclass
	if (rows > 20) then
		stickyclass 		= cssclass.sticky -- only sticky if more than 20 rows
	end
	-- /
	
	-- First header column (charts)
	local tableheaderfirst = mw.html.create ("th")
		:addClass(mobheaderclass)
		:css("width", "250px")
		:node( mw.html.create ("span")
				:addClass(cssclass.hidemobile)
				:wikitext(label.charts)
		)
		:node( mw.html.create ("span")
				:addClass(cssclass.mobileonly)
				:wikitext(tableheaderfirstyear)
		)
		:wikitext(yeardisplay)
		:wikitext(source or "")
	-- /
	
	-- Second header column (chart position)
	local tableheadersecond = mw.html.create ("th")
		:addClass(headerclass)
		:css("width", "150px")
		:node ( mw.html.create ("span")
					:addClass(cssclass.hidemobile)
					:wikitext(label.peak)
		)
	-- /
	
	-- Third header column (weeks/months)	
	local tableheaderthird = mw.html.create ("th")
		:addClass(headerclass)
		:css("width", "90px")
		:wikitext(weeksmonths)
	--/
	
	-- Alternative layout for year-end charts	
	if year then
		tableheadersecond = mw.html.create ("th")
			:addClass(headerclass)
			:css("width", "90px")
			:wikitext(label.position)
		tableheaderthird = nil
	end
	-- /
	
	-- table caption
	local chartposheadcaption
	if tablecaption then
		chartposheadcaption = mw.html.create ("caption")
								:wikitext( tostring(tablecaption) )
	end
	-- /
	
	-- table header
	local chartposheadheader = mw.html.create ("tr")
								:node(tableheaderfirst)
								:node(tableheadersecond)
								:node(tableheaderthird)
	-- /
	
	-- start building table
	local chartposheadtable = mw.html.create ("table")
								:addClass("wikitable")
								:addClass(cssclass.charttable)
								:addClass(zebraclass)
								:addClass(stickyclass)
								:css("max-width", "100%")
								:css("break-inside", "avoid")
								:node(chartposheadcaption)
								:node(chartposheadheader)
	-- /
	
	-- add single rows
	for row = 1, rows do
		local singlerow = entry[row]
		-- content substitutions, link fixes
		if months then
			singlerow = singlerow
				:gsub ("<span class='WO'></span>", "&nbsp;" .. label.wk)
		else
			singlerow = singlerow
				:gsub ("<span class='WO'></span>", "")
		end
		if not weeks then
			singlerow = singlerow
				:gsub ("<span class='MT'>&nbsp;" .. label.mt .. "</span>", "")
		end
		if year then
			if string.match (singlerow, "%[%[Liste der") then
				local temp = ""
				temp = string.match (singlerow, "%[%[(Liste der Nummer%-eins%-.-)|")
				local yearnumberonelist = temp
					:gsub ("Nummer%-eins%-", "Jahres-Nummer-eins-")
					:gsub ("%s%(%d%d%d%d%)", "")
				if mw.title.new( yearnumberonelist ).exists then
					singlerow = singlerow
						:gsub (temp, yearnumberonelist)
				end
			end
		end
		-- /
		
		chartposheadtable:node(singlerow)
		
	end
	-- /
	
	local ret = frame:extensionTag( "templatestyles", nil, { src = "Charttabelle/styles.css" } ) .. tostring (chartposheadtable)
	
	-- content substitutions
	if grey then
		ret = ret:gsub("%[%[File:.-]]&nbsp;", "")
	end
	
	return ret

end



-- Charts - chart positions table entry
p.chartposrow = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local countryraw		= parameters[1]
	local position			= parameters[2]
	local weeks 			= parameters[3]
	local ref				= parameters[param.source]
	local year				= parameters[param.year]
	-- /
	
	-- service links
	local sltemporary = "<span style='display:none'>[[Template:Chartplatzierungen/Wartung/vorläufig]]</span>"
	--
	
	-- derived parameters
	local country
	local brackets
	if countryraw then
		country = string.match (countryraw, "(.*)%s%(.*%)") or countryraw
		brackets = string.match (countryraw, ".*%s(%(.*%))")
	end
	local countrydisplay = countryfunctions.countryflag (country, 2, 1, 3, "chartpos")
	if brackets then
		if countrydisplay:match ("%(") then
			countrydisplay = countrydisplay:gsub ("%(.-%)", brackets )
		else
			countrydisplay = countrydisplay .. brackets
		end
	end
	local weekdisplay
	local months
	local mobileweeks
	local mobileweekdisplay
	if weeks then
		if weeks == "" then
			weeks = "&hellip;" .. sltemporary
		end
		mobileweekdisplay = weeks .. "&nbsp;" .. label.wk
		weekdisplay = weeks .. "<span class='WO'></span>"
		if string.match (weeks, label.mt) then
			if weeks == label.mt then
				months = "&hellip;" .. sltemporary
			else
				months = string.gsub (weeks, "%s?" .. label.mt, "")
			end
			mobileweekdisplay = months .. "&nbsp;" .. label.mt
			weekdisplay = months .. "<span class='MT'>&nbsp;" .. label.mt .. "</span>"
		end
		mobileweeks = mw.html.create ("span")
						:addClass(cssclass.mobileonly)
						:css("font-size", "smaller")
						:wikitext(" (" .. mobileweekdisplay .. ")")
	end
	-- /
	
	-- link number one
	if position then
		if position == "1" or string.match(position, "^1%D") then
			position = countryfunctions.numberonelinks (position, country, year)
		end
	end
	-- /
	
	-- first column (country + sources)
	local chartposrowfirst = mw.html.create ("td")
								:wikitext(countrydisplay)
								:wikitext(ref or "")
	-- /
	
	-- second column (chart position + mobile weeks/months)
	local chartposrowsecond = mw.html.create ("td")
								:css("text-align", "center")
								:wikitext(position)
								:node(mobileweeks)
	-- /
	
	-- third column (weeks or months on chart)
	local chartposrowthird
	if weeks then
		chartposrowthird = mw.html.create ("td")
							:addClass(cssclass.hidemobile)
							:css("text-align", "center")
							:wikitext(weekdisplay)
	end
	-- /
	
	-- build table row
	local ret = mw.html.create ("tr")
					:node(chartposrowfirst)
					:node(chartposrowsecond)
					:node(chartposrowthird)
	-- /
	
	return ret
end



-- Infobox Chartplatzierungen - chart positions infobox
p.chartinfobox = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end -- always [?]
	
	-- direct template parameters
	local file			= parameters[param.image]
	local caption		= parameters[param.imagecaption]
	local temporary 	= parameters[param.temporary]

	local albums		= parameters[param.albums]
	local eps			= parameters[param.eps]
	local singles		= parameters[param.singles]
	local dvds			= parameters[param.dvds]

	local refalbums 	= parameters[param.refalbums]
	local refeps		= parameters[param.refeps]
	local refsingles	= parameters[param.refsingles]
	local refdvds		= parameters[param.refdvds]
	local source		= parameters[param.sources]
	-- /
	
	-- derived parameters
	local rformats		= { albums, eps, singles, dvds }
	local refs			= { refalbums, refeps, refsingles, refdvds }
	local refrow
	
	local temporaryweeks
	for temp = 1, 4 do
		if rformats[temp] then
			if string.match (rformats[temp], "%(&hellip;" ) then
				temporaryweeks = true
			end
		end
	end
	-- /
	
	-- service links
	local slsourceparam = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Quellen-Parameter]]</span>"
	local slnosource	= "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/ohne Quellen]]</span>"
	local sltemporary	= "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/vorläufige Chartplatzierung]]</span>"
	-- /
	
	-- image + caption
	local firstrow
	local secondrow
	if file then
		local imagecell
		if file ~= "" then
			imagecell = mw.html.create ("td")
						:css("text-align", "center")
						:wikitext("[[File:" .. file .. "|210px|" .. (caption or mw.title.getCurrentTitle().text) .. "]]")
			firstrow = mw.html.create ("tr")
						:node(imagecell)
			if caption then
				local captioncell
				if caption ~= "" then
					captioncell = mw.html.create ("td")
									:css("text-align", "center")
									:css("font-size", "smaller")
									:wikitext(caption)
					secondrow = mw.html.create ("tr")
									:node(captioncell)
				end
			end
		end
	end
	-- /
	
	-- header
	local headertemporary
	if temporaryweeks then
		headertemporary = mw.html.create ("span")
							:css("font-size", "12px")
							:css("font-stretch", "condensed")
							:wikitext("<br />(" .. label.temporary .. ")")
	end
	
	local headertitle = mw.html.create ("span")
							:css("font-size", "20px")
							:css("font-stretch", "condensed")
							:wikitext(label.chartpositions)
					
	local headerlink = mw.html.create ("span")
							:css("font-size", "smaller")
							:wikitext("<br />[[" .. label.chartinfolink .. "|" .. label.chartinfolinktext .. "]]")
	
	local headercell = mw.html.create ("td")
							:css("background-color", "#F3F3F3")
							:css("text-align", "center")
							:node(headertitle)
							:node(headertemporary)
							:node(headerlink)
					
	local thirdrow = mw.html.create ("tr")
							:node(headercell)
	-- /
	
	-- start building infobox
	local infoboxtable = mw.html.create ("table")
							:addClass("infobox")
							:addClass(cssclass.chartbox)
							:node(firstrow)
							:node(secondrow)
							:node(thirdrow)
	-- /
	
	-- content
	for section = 1, 4 do
		local titles = {label.albums, label.eps, label.singles, label.dvds}
		if rformats[section] then
			if rformats[section] ~= "" then
				local innertable = mw.html.create ("table")
										:css("border-collapse", "collapse")
										:css("display", "table")
										:wikitext(rformats[section])
										
				local sectiontitle = mw.html.create ("span")
										:css("font-size", "larger")
										:css("font-weight", "bold")
										:wikitext(titles[section])
										
				local titlerowcell = mw.html.create ("td")
										:css("padding", "0 .3em")
										:css("background", "#EAECF0")
										:css("color", "#202122")
										:node(sectiontitle)
										:wikitext(refs[section] or "")
										
				local contentrowcell = mw.html.create ("td")
										:css("padding", "0 .3em .5em .3em")
										:node(innertable)
										
				local titlerow = mw.html.create ("tr")
										:node(titlerowcell)
				local contentrow = mw.html.create ("tr")
										:node(contentrowcell)

				-- add sections to infobox
				infoboxtable
					:node(titlerow)
					:node(contentrow)
				-- /
				
				if string.match (rformats[section], "<!%-%-%$QUELLEZEILE%$%-%->") then
					refrow = true
				end
			end
		end
	end
	-- /
	
	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	ret = ret .. tostring (infoboxtable)
	
	-- create service links
	if source then
		ret = ret .. slsourceparam
	elseif not refalbums and not refsingles and not refeps and not refdvds and not refrow then
		ret = ret .. slnosource
	end
	if temporary then
		ret = ret .. sltemporary
	end
	-- /
	
	return ret
	
end



-- Infobox Chartplatzierungen/Werk - chart positions infobox entry
p.chartinfoboxentry = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- service links
	local slmissingtitle = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Titel fehlt]]</span>"
	-- /
	
	-- correct chart links according to rformat
	local templatename = frame:getParent():getTitle()
	local rformat = string.match (templatename, ".*:(%a*)")
	local rows = {}
	local i = 0
	for k, v in ipairs (parameters) do
		if rformat == param.tmpsingle then
			v = countryfunctions.singlechartlink (v)
		end
		
		if #v > 0 then
			i = i + 1
			rows[i] = v
		end
	end
	-- /
	
	local title = ""
	local rownumberstart = 0
	
	-- valididty of title parameter
	if rows[1] then
		if rows[1]:match("^|") then
			title = slmissingtitle
			rownumberstart = 1
		else
			title = rows[1]
			rownumberstart = 2
			if rows[1] == "" then
				title = slmissingtitle
			end
		end
	end
	--/
	
	local ret
	
	-- content (rows)
	local titlecell = mw.html.create ("td")
						:attr("colspan", "6")
						:css("font-size", "95%")
						:css("font-weight", "bold")
						:wikitext(title)
	local titlerow = mw.html.create ("tr")
						:node(titlecell)
						
	ret = tostring(titlerow)
	
	for row = rownumberstart, #rows do
		local contentrow = mw.html.create ("tr")
							:addClass(cssclass.chartboxrow)
							:node(rows[row])
		ret = ret .. tostring (contentrow)
	end
	-- /
	
	return ret
end



-- Charts - chart positions infobox row
p.chartinfoboxrow = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local country = parameters[1]
	if country then
		country = mw.text.trim (country)
	end
	local poscert = parameters[2]
	if poscert then
		poscert = mw.text.trim (poscert)
	else
		poscert = ""
	end
	local entrydate = parameters[3]
	if entrydate then
		entrydate = mw.text.trim (entrydate)
	end
	local weeks = parameters[4]
	if weeks then
		weeks = mw.text.trim (weeks)
	end
	local ref = parameters[5]
	local year = parameters[param.year]
	if not year and entrydate then
		year = string.match (entrydate, "(%d%d%d%d)$")
	end
	-- /
	
	-- derived parameters
	local position
	local certification
	local certref
	
	certification = string.match (poscert, "%s(%d?%d?%d?[SGPD].*)")  -- "%s(%d?%d?%d?[SGPD]%A+.*)" ???
	if certification then
		position = poscert:gsub ("%d?%d?%d?[SGPD].*", "")
	else
		position = poscert
	end
	position = mw.text.trim (position)
	if string.match (position, "%A?[SGPD]%A?") then
		certification = position
		position = ""
	end
	if certification then
		if string.match (certification, "ref") then
			certref = string.match (certification, "[%a%d%s%+%(%)]*(.+)")
		end
	end
	-- /
	
	-- service links
	local slbelgium = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Belgien]]</span>"
	local sltemporary = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/vorläufig"
	if year then
		if tonumber(year) > 2019 then
			sltemporary = sltemporary .. "/" .. year
		end
	end
	sltemporary = sltemporary .. "]]</span>"
	local sldots = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Punkte]]</span>"
	local slwrongdate = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Datum falsch]]</span>"
	-- /
	
	-- start building table row
	local firstcolumn = mw.html.create ("td")
							:css("width", "3%")
							:css("background", "transparent")
							:wikitext("&nbsp;")
	local secondcolumn = mw.html.create ("td")
							:css("width", "12%")
							:css("font-size", "95%")
							:css("line-height", "90%")
							:wikitext( countryfunctions.countrycol (country, 1, nil, "infobox") )
	if (country == "BEW" or country == "BEF") and (tonumber(year) or 0) < 1995 then
		secondcolumn:wikitext( slbelgium )
	end
	
	-- chart position
	local thirdcolumn = mw.html.create ("td")
							:css("width", "27%")
							:css("font-size", "95%")
							:css("line-height", "90%")
							:css("font-weight", "bold")
							:css("text-align", "center")

	if position then
		if position == "1" or string.match(position, "^1%D") then
			position = countryfunctions.numberonelinks (position, country, year)
		end
		
		thirdcolumn:wikitext( position )
	end
	-- /
	
	-- certification
	if certification then
		certification = "&thinsp;" .. certicon.certicon(frame, certification, nil, "16")
	else
		certification = ""
	end
	thirdcolumn:wikitext( certification )
	if position == "" then
		thirdcolumn:wikitext("<span style='font-size:85%;'>" .. (certref or "") .. "</span>")
		certref = ""
	end
	-- /
	
	local fourthcolumn = mw.html.create ("td")
							:css("width", "30%")
							:css("font-size", "smaller")
							:wikitext(entrydate or "")
	
	-- weeks or months on charts
	local fifthcolumn = mw.html.create ("td")
							:css("width", "23%")
							:css("font-size", "smaller")
							:css("text-align", "right")
							:css("padding-left", "5px")

	if weeks then
		if weeks == "" or weeks == "…" or weeks == "..." then
			weeks = "&hellip;" .. sltemporary
			if weeks == "..." then
				weeks = weeks .. sldots
			end
		end
		if string.match (weeks, label.mt) then
			fifthcolumn:wikitext( "(" .. weeks .. ")" )
		else
		    fifthcolumn:wikitext( "(" .. weeks .. "&nbsp;" .. label.wk .. ")" )
		end
	end
	-- /
	
	local sixthcolumn = mw.html.create ("td")
							:css("width", "5%")
							:css("font-size", "smaller")
							:wikitext( (ref or "") .. (certref or "") )


	local ret = tostring (firstcolumn) .. tostring (secondcolumn) .. tostring (thirdcolumn) .. tostring (fourthcolumn) .. tostring (fifthcolumn) .. tostring (sixthcolumn)
	if ref then ret = ret .. "<!--$QUELLEZEILE$-->" end
	
	-- insert service link wrong dates
	if entrydate then
		if #entrydate < 4 then
			ret = ret .. slwrongdate
		end
	end
	-- /
	
	return ret
end



-- Wechsel zwischen Chartplatzierungen-Zeile und Chartbox-Zeile - switch between chart positions table row and infobox row
p.chartrows = function (frame)
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	if parameters[param.source] then
		return p.chartposrow(frame)
	else
		return p.chartinfoboxrow(frame)
	end
	
end



-- AfM-Tabelle - table for certifications
p.certificationtable = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- get content and define rows
	local entry = {}
	for k, v in ipairs (parameters) do
		entry [k] = v
	end
	local rows = 0
	repeat
		rows = rows + 1
		local entry = "" .. rows
	until not parameters[entry]
	rows = rows - 1
	-- /
	
	-- direct template parameters
	local statistics				= parameters[param.statistics]
	local main						= parameters[param.mainarticle]
	local note						= parameters[param.certnote]
	local source					= parameters[param.source]
	local nosilver					= parameters[param.deactsilver]
	local nodiamond 				= parameters[param.deactdiamond]
	
	local silver					= parameters[param.totsilver]
	local gold						= parameters[param.totgold]
	local platinum					= parameters[param.totplatinum]
	local diamond					= parameters[param.totdiamond]
	local number					= parameters[param.totnumber]
	
	local grey						= parameters[param.grey]
	-- /
	
	local headerclass				= cssclass.headerrow
	local mobheaderclass			= cssclass.headercell
	if grey then
		headerclass 				= cssclass.headerrowgrey
		mobheaderclass				= cssclass.headercellgrey
	end
	local pagename					= mw.title.getCurrentTitle().text
	local sicon 					= "[[File:Silver record icon.svg|15px|link=]] "
	local gicon 					= "[[File:Gold record icon.svg|15px|link=]] "
	local picon 					= "[[File:Platinum record icon.svg|15px|link=]] "
	local dicon 					= "[[File:Diamond record icon.svg|15px|link=]] "
	if grey then
		sicon, gicon, picon, dicon	= "", "", "", ""
	end

	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	-- add explanation about the allocation of certifications in chart table
	if statistics and not note and not main and not string.match (pagename, label.certpagename) then
		local pagenameroot = string.match ( pagename, "(.+)" .. label.discpagename ) or pagename
		local certifications = pagenameroot .. label.certpagename
		if mw.title.new( certifications ).exists == false then
			ret = ret .. "\n<span style='font-style:italic;font-size:smaller;'>" .. label.certnotedefault .. "</span>"
		end
	end
	
	-- start building table (normal/statistics)
	ret = ret .. "\n{| class='wikitable "
	if statistics then
		ret = ret .. "charts-table"
	else
		ret = ret .. "charts-ctable"
	end
	if grey then
		ret = ret .. " charts-zebra"
	else
		ret = ret .. " charts-zebragrey"
		if not statistics then
			ret = ret .. "2"
		end
	end
	if (rows > 20) then
		ret = ret .. " charts-stickyhead" -- only sticky if more than 20 rows
	end
	
	-- table header
	if statistics then
		ret = ret .. " sortable' style='max-width:100%' \n|-"
		ret = ret .. "\n! style='width:250px;' class='" .. mobheaderclass .. "' | <span class='charts-hidm'>" .. label.region .. "</span><span class='charts-monl'>" .. label.certificationsfull .."<br /><span class='charts-mh'>(" .. label.region .. ", " .. label.certifications .. ", " .. label.sales .. ", " .. label.sources .. ")</span></span> \n!"
		if not nosilver then
			ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. sicon .. label.silver .. " !! "
		end
		ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. gicon .. label.gold .. " !! "
		ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. picon .. label.platinum
		if not nodiamond then
			ret = ret .. " !! class='" .. headerclass .. "' data-sort-type='number' | " .. dicon .. label.diamond
		end
		ret = ret .. "\n! style='width:90px;' class='" .. headerclass .. "' data-sort-type='number' | " .. label.sales
		ret = ret .. "\n ! class='unsortable " .. headerclass .. "' | " .. label.sources
	else
		ret = ret .. "' style='max-width:100%;' \n|-"
		ret = ret .. "\n! style='width:250px;' class='" .. headerclass .. "' | " .. label.region
		ret = ret .. "\n! style='width:150px;' class='" .. mobheaderclass .. "' | Aus&shy;zeich&shy;nung" .. "<span class='charts-monl'>&shy;en für Mu&shy;sik&shy;ver&shy;käu&shy;fe<br /><span class='charts-mh'>(" .. label.region .. ", " .. label.certification .. ", " .. label.sales .. ")</span></span>" .. (source or "")
		ret = ret .. "\n! style='width:90px;' class='" .. headerclass .. "' data-sort-type='number' | " .. label.sales
	end
	
	-- single rows
	ret = ret .. "\n|-\n"
	for row = 1, rows do
		local content = entry[row]
		if statistics then
			-- delete empty columns
			if nosilver then
				content = string.gsub (content, '<td class="charts%-hidm" style="text%-align:center"><span style="display:none">0! S</span>&mdash;</td>', '')
			end
			if nodiamond then
				content = string.gsub (content, '<td class="charts%-hidm" style="text%-align:center"><span style="display:none">0! D</span>&mdash;</td>', '')
			end
		end
		ret = ret .. content
	end
	
	ret = ret .. "|-"
	if statistics then
		ret = ret .. "class='sortbottom"
		if not grey then ret = ret .. " charts-yelst" end
		ret = ret .. "' style='font-weight:bold;'\n| " .. label.total
		
		if not nosilver then
			if silver and silver ~= "" and silver ~= "0" then
				local silvercert = silver .. label.silvershort
				ret = ret .. "\n| style='text-align:center;' |"
				-- mobileview
				ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, silvercert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='charts-hidm'>" .. silver .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | &mdash;"
			end
		end
		
		if gold and gold ~= "" and gold ~= "0" then
			local goldcert = gold .. label.goldshort
			ret = ret .. "\n| style='text-align:center;' |"
			-- mobileview
			ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, goldcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='charts-hidm'>" .. gold .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | &mdash;"
		end
		
		if platinum and platinum ~= "" and platinum ~= "0" then
			local platinumcert = platinum .. label.platinumshort
			ret = ret .. "\n| style='text-align:center;' |"
			-- mobileview
			ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, platinumcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='charts-hidm'>" .. platinum .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | &mdash;"
		end
		
		if not nodiamond then
			if diamond and diamond ~= "" and diamond ~= "0" then
				local diamondcert = diamond .. label.diamondshort
				ret = ret .. "\n| style='text-align:center;' |"
				-- mobileview
				ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, diamondcert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='charts-hidm'>" .. diamond .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | &mdash;"
			end
		end
		
		ret = ret .. "\n| colspan='2' |"
	else
		if number then
			if not grey then ret = ret .. "class='charts-yelst' " end
			ret = ret .. "style='font-style:italic;'\n| " .. label.total .. "\n| style='text-align:center;' |"
			if silver or gold or platinum or diamond then
				if silver then
					ret = ret .. sicon .. silver .. "× " .. label.silver .. "<br />"
				end
				if gold then
					ret = ret .. gicon .. gold .. "× " .. label.gold .. "<br />"
				end
				if platinum then
					ret = ret .. picon .. platinum .. "× " .. label.platinum .. "<br />"
				end
				if diamond then
					ret = ret .. dicon .. diamond .. "× " .. label.diamond .. "<br />"
				end
			else
				ret = ret .. "&mdash;"
			end
			ret = ret .. "\n| style='text-align:right;' | <b>" .. number .. "</b>"
		end
	end
	ret = ret .. "\n|}"
	-- / table end
	
	-- add link to main article
	if main then
		ret = ret .. "\n<span style='font-style:italic; font-size:smaller;'>" .. label.mainarticle .. ": [[" .. main .. "]]</span>"
	end
	
	-- content substitutions
	if grey then
		ret = ret:gsub("%[%[File:.-]]&nbsp;", "")
	end

return ret

end



-- AfM - certification table rows
p.certificationtablerow = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local silver				= parameters[param.silver]
	local gold					= parameters[param.gold]
	local platinum				= parameters[param.platinum]
	local diamond				= parameters[param.diamond]
	local sum2					= parameters[2]
	local source				= parameters[param.source]
	
	local country				= parameters[1]
	local certification 		= parameters[2]
	local number				= parameters[3]
	local sum					= parameters[4]
	-- /
	
	-- derived parameters
	local countrydisplay		= countryfunctions.countryflag (country, 4, 1, 5, "certification")
	local sumtest
	if parameters[2] then 
		sumtest 				= parameters[2]:gsub("%(", ""):gsub("%)", ""):gsub("%.", "")
	end
	local statisticstable
	if silver or gold or platinum or diamond or tonumber(sumtest) then
		statisticstable			= true
		certification			= false
	end
	-- /
	
	-- service links
	local slcustomcert			= "<span style='display:none'>[[Template:AfM-Tabelle/Wartung/Manuelle Auszeichnung]]</span>"
	local slcustomcerttemplate	= "<span style='display:none'>[[Template:AfM-Tabelle/Wartung/Schallplattenvorlage]]</span>"
	-- /
	
	-- first column (country)
	local firstcolumnsource
	if not statisticstable then
		firstcolumnsource		= source or ""
	end
	local certtablerowfirst 	= mw.html.create ("td")
									:wikitext(countrydisplay)
									:wikitext(firstcolumnsource)
	-- /
	
	-- silver column
	local certtablerowsilver
	if silver ~= "n" then
		if silver and silver ~= "" and silver ~= "0" then
			local silvercert = silver .. param.silver
			certtablerowsilver 		= mw.html.create ("td")
										:css("text-align", "center")
										:attr("data-sort-value", silver)
										:node( mw.html.create ("span")
												:addClass(cssclass.mobileonly)
												:wikitext(certicon.certicon(frame, silvercert, "text"))
										)
										:node( mw.html.create ("span")
												:addClass(cssclass.hidemobile)
												:wikitext(silver)
										)
		else
			certtablerowsilver 		= mw.html.create ("td")
										:css("text-align", "center")
										:addClass(cssclass.hidemobile)
										:node( mw.html.create ("span")
												:css("display", "none")
												:wikitext("0! " .. param.silver)
										)
										:wikitext("&mdash;")
		end
	end
	-- /
	
	-- gold column
	local certtablerowgold
	if gold and gold ~= "" and gold ~= "0" then
		local goldcert = gold .. param.gold
		certtablerowgold 		= mw.html.create ("td")
									:css("text-align", "center")
									:attr("data-sort-value", gold)
									:node( mw.html.create ("span")
											:addClass(cssclass.mobileonly)
											:wikitext(certicon.certicon(frame, goldcert, "text"))
									)
									:node( mw.html.create ("span")
											:addClass(cssclass.hidemobile)
											:wikitext(gold)
									)
	else
		certtablerowgold 		= mw.html.create ("td")
									:css("text-align", "center")
									:addClass(cssclass.hidemobile)
									:node( mw.html.create ("span")
											:css("display", "none")
											:wikitext("0! " .. param.gold)
									)
									:wikitext("&mdash;")
	end
	-- /
	
	-- platinum column
	local certtablerowplatinum
	if platinum and platinum ~= "" and platinum ~= "0" then
		local platinumcert = platinum .. param.platinum
		certtablerowplatinum 	= mw.html.create ("td")
									:css("text-align", "center")
									:attr("data-sort-value", platinum)
									:node( mw.html.create ("span")
											:addClass(cssclass.mobileonly)
											:wikitext(certicon.certicon(frame, platinumcert, "text"))
									)
									:node( mw.html.create ("span")
											:addClass(cssclass.hidemobile)
											:wikitext(platinum)
									)
	else
		certtablerowplatinum	= mw.html.create ("td")
									:css("text-align", "center")
									:addClass(cssclass.hidemobile)
									:node( mw.html.create ("span")
											:css("display", "none")
											:wikitext("0! " .. param.platinum)
									)
									:wikitext("&mdash;")
	end
	-- /
	
	-- diamond column
	local certtablerowdiamond
	if diamond ~= "n" then
		if diamond and diamond ~= "" and diamond ~= "0" then
			local diamondcert = diamond .. param.diamond
			certtablerowdiamond		= mw.html.create ("td")
										:css("text-align", "center")
										:attr("data-sort-value", diamond)
										:node( mw.html.create ("span")
												:addClass(cssclass.mobileonly)
												:wikitext(certicon.certicon(frame, diamondcert, "text"))
										)
										:node( mw.html.create ("span")
												:addClass(cssclass.hidemobile)
												:wikitext(diamond)
										)
		else
			certtablerowdiamond		= mw.html.create ("td")
										:css("text-align", "center")
										:addClass(cssclass.hidemobile)
										:node( mw.html.create ("span")
												:css("display", "none")
												:wikitext("0! " .. param.diamond)
										)
										:wikitext("&mdash;")
		end
	end
	-- /
	
	-- statistic sum column
	local certtablerowstatsum
	if sum2 and sum2 ~= "" and sum2 ~= "0" then
		certtablerowstatsum			= mw.html.create ("td")
										:css("text-align", "right")
										:wikitext(sum2)
	else
		certtablerowstatsum			= mw.html.create ("td")
										:css("text-align", "right")
										:addClass(cssclass.hidemobile)
										:node( mw.html.create ("span")
											:css("display", "none")
											:wikitext("0!")
										)
										:wikitext("&mdash;")
	end
	-- /
	
	-- statistic source column
	local certtablerowsource
	if source and source ~= "" and source ~= "0" then
		certtablerowsource			= mw.html.create ("td")
										:wikitext(source)
	else
		certtablerowsource			= mw.html.create ("td")
										:addClass(cssclass.hidemobile)
										:wikitext("")
	end
	-- /
	
	-- certification column
	local certtablerowcert
	local certificationdisplay
	if not certification then
		certificationdisplay		= "&mdash;"
	elseif certification == "" or certification == "-" or certification == "—" then
		certificationdisplay		= "&mdash;"
	elseif number == "" or number == "-" or number == "—" then
		certificationdisplay		= certification or ""
	elseif certification == "D+P" or certification == "P+D" then
		certificationdisplay		= "[[File:Diamond record icon.svg|15px|link=]][[File:Platinum record icon.svg|15px|link=]]&nbsp;" .. number .. "×&nbsp;Platin"
	else
		certification				= certification .. (number or "")
		local icontype				= "text"
		certificationdisplay		= certicon.certicon(frame, certification, icontype)
	end
	if certification then
		if string.match (certification, "Datei") and not string.match (certification, "verweis=") and not string.match (certification, "link=") then
			certificationdisplay	= certificationdisplay .. slcustomcert
		end
		if string.match (certification, "charts-certc") or string.match (certification, "Schallplatte") or string.match (certification, "File") then
			certificationdisplay	= certificationdisplay .. slcustomcerttemplate
		end
	end
		certtablerowcert			= mw.html.create ("td")
										:wikitext(certificationdisplay)
	-- /
	
	-- sum column
	local certtablerowsum			= mw.html.create ("td")
										:wikitext(sum or "&mdash;")
	-- /
	
	-- build table row
	local ret
	if statisticstable then
		ret 			= mw.html.create ("tr")
							:node(certtablerowfirst)
							:node(certtablerowsilver)
							:node(certtablerowgold)
							:node(certtablerowplatinum)
							:node(certtablerowdiamond)
							:node(certtablerowstatsum)
							:node(certtablerowsource)
	else
		ret 			= mw.html.create ("tr")
							:node(certtablerowfirst)
							:node(certtablerowcert)
							:node(certtablerowsum)
	end
	-- /

return ret

end


-- AfM - inline certification
p.certification = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local certification = parameters[1]
	local number = parameters[2]
	local sum = parameters[3]
	-- /
	
	local ret = ""
	if certification == "D+P" or certification == "P+D" then
		ret = ret .. "[[File:Diamond record icon.svg|15px|link=]][[File:Decuple platinum record icon.svg|15px|link=]]&nbsp;" .. number .. "×&nbsp;Platin"
	else
		certification = certification .. (number or "")
		local icontype = "text"
		ret = ret .. certicon.certicon(frame, certification, icontype)
	end
	if sum then
		ret = ret .. " (" .. sum .."+)"
	end
	
	return frame:preprocess (ret)
	
end


-- Wechsel zwischen AfM/AfM2 - switch between certificationtablerow and certification
p.certifications = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	local ID = parameters[1]
	local certnames = { 
		["S"] = true, 
		["Silber"] = true, 
		["G"] = true, 
		["Gold"] = true, 
		["P"] = true, 
		["Platin"] = true, 
		["D"] = true, 
		["Diamant"] = true, 
		["P+G"] = true, 
		["G+P"] = true, 
		["D+P"] = true, 
		["P+D"] = true
	}
	
	if certnames[ID] then
		return p.certification(frame)
	else
		return p.certificationtablerow(frame)
	end
	
end



-- Schallplatte - formatted inline certification
p.inlinecerticon = function (frame)
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	local raw = parameters[1] or ""
	local inline = frame:extensionTag( "templatestyles", nil, { src = templatestyles } ) .. certicon.certicon (frame, raw)
	inline = inline
		:gsub ("<div", "<span")
		:gsub ("</div>", "</span>")
	if raw:match("%d") then
		inline = inline .. " "
	end
	
	return inline
end



-- Nummer-eins-Hits - table for no. 1 hits and albums
p.no1table = function (frame)
	local parameters = frame.args
	if not parameters.Inhalt then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local listtype = parameters.Art or "Hits"
	local country = parameters.Land or "Land"
	local name = parameters.Bezeichnung
	if name == "" then
		name = nil
	end
	local months = parameters.Monate
	if months == "" then
		months = nil
	end
	local content = parameters.Inhalt or ""
	-- /
	
	-- derived parameters
	local pagename = mw.title.getCurrentTitle().text
	local currentyear = tonumber ( os.date( "%Y" ) )
	local year = string.match (pagename, ".+%((%d%d%d%d)%)") or currentyear
	local prevyear = year - 1
	local nextyear = year + 1
	local linkprev
	local linknext
	if string.match (pagename, "%d%d%d%d") then
		linkprev = string.gsub (pagename, "%d%d%d%d", prevyear)
		linknext = string.gsub (pagename, "%d%d%d%d", nextyear)
	else
		linkprev = pagename .. " (" .. prevyear .. ")"
		linknext = pagename .. " (" .. nextyear .. ")"
	end
	local listlink
	if string.match (pagename, ".+%s%(%d%d%d%d%)") then
		listlink = string.match (pagename, "(.+)%s%(%d%d%d%d%)")
	else
		listlink = pagename
	end
	
	if listtype == "Alben" and string.match (pagename, "Hits") then
		local templistlink = "Liste der Nummer-eins-" .. listtype .. " in " .. countryfunctions.no1tablecountry (country, "countryid")
		if mw.title.new( templistlink ).exists then
			listlink = templistlink
		end
	end
	if listtype == "Jahr" then
		local yearlistlink = "Liste der Jahres-Nummer-eins-Hits in " .. countryfunctions.no1tablecountry (country, "countryid")
		if mw.title.new( yearlistlink ).exists then
			listlink = yearlistlink
		end
	end

	local sectionlink = "#"
	if listtype == "Jahr" then
		sectionlink = sectionlink .. "Jahreshitparaden"
	elseif listtype == "JahrA" or listtype == "JahrS" then
		sectionlink = sectionlink .. "Jahreshitparade"
	else
		sectionlink = sectionlink .. (listtype or "")
	end
	if name then
		if string.match (name, "Wallon") then
			sectionlink = sectionlink .. "_2"
		end
	end
	
	local colour1 = countryfunctions.no1tablecountry (country, "colour1")
	local colour2 = countryfunctions.no1tablecountry (country, "colour2")
	local rowcolour = countryfunctions.no1tablecountry (country, "rowcolour")
	local flag = countryfunctions.no1tablecountry (country, "flag")
	local firstyear = countryfunctions.no1tablecountry (country, "firstyear", listtype)
	-- /
	
	-- check number of rows
	local rownumber
	content, rownumber = string.gsub (content, "class='newno1tablerow' ", "")
	-- /
	
	-- fix colouring of divider rows
	if string.match (content, 'class="sortbottom"') then
		content = string.gsub (content, "background:#EEEEEE;", "background:" .. colour2 .. ";")
	end
	-- /

	-- build table	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	
	-- navigation header
	ret = ret .. "\n{| class='charts-no1table' style='width:100%;border-spacing:0px;display:table;' \n |- style='background-color:" .. colour1 .. "' \n| style='width:15%;line-height:1em;' |"
	if prevyear >= tonumber(firstyear) then
		ret = ret .. "[[" .. linkprev .. sectionlink .. "|<span class='charts-hidm'>← </span>" .. prevyear .. "<span class='charts-monl'><br />←</span>]]"
	end
	
	ret = ret .. "\n| colspan='3' style='text-align:center; width:70%' |"
	ret = ret .. (frame:preprocess(flag) or "") .. "&nbsp;[[" .. mw.text.trim (listlink) .."|" .. listlink:gsub ("Liste der ", "<span class='charts-hidm'>Liste der </span>") .. "]]"
	if name then
		ret = ret .. "&nbsp;(" .. name .. ")"
	end
	
	ret = ret .. "\n| style='text-align:right;width:15%;line-height:1em;' |"
	if tonumber(year) < currentyear then
		ret = ret .. "[[" .. linknext .. sectionlink .. "|" .. nextyear .. " <br class='charts-monl' />→]]"
	end
	ret = ret .. "\n|- \n| colspan='5' |"
	-- /
	
	-- table header
	ret = ret .. "\n{| class='wikitable charts-zebra sortable"
	if (rownumber > 5) then
		ret = ret .. " charts-stickyhead" -- only sticky if more than 5 rows
	end
	if listtype ~= "Jahr" and listtype ~= "JahrA" and listtype ~= "JahrS" then
		ret = ret .. " charts-table'"
	else
		ret = ret .. "'"
	end
	ret = ret .. " style='width:100%; background-color:" .. rowcolour .."; color:var(--color-base, #202122); border:none; margin:0px;'"
	ret = ret .. "\n|- style='background-color:" .. colour2 .. "'"
	if listtype ~= "JahrA" and listtype ~= "JahrS" then
		ret = ret .. "\n! style='background-color:" .. colour2 .. "; border:none;"
		if listtype == "Jahr" then
			ret = ret .. "border-bottom: 1pt solid white; width:45%' class='unsortable charts-th' | <span style='font-size:larger'>Singles</span>"
		else
			ret = ret .. "text-align:left; width:15%' class='charts-trh' | Zeitraum "
			ret = ret .. "!! data-sort-type='number' style='background-color:" .. colour2 .. "; border:none; text-align:center; width:5%' class='charts-trh' | "
			if months then
				ret = ret .. "<abbr title='Monate insgesamt auf Platz eins'>Mt.<br /><span style='font-size:smaller'>ges.</span></abbr>"
			else
				ret = ret .. "<abbr title='Wochen insgesamt auf Platz eins'>Wo.<br /><span style='font-size:smaller'>ges.</span></abbr>"
			end
		end
	end
	ret = ret .. "\n! style='background-color:" .. colour2 .. "; border:none;"
	if listtype == "Jahr" or listtype == "JahrA" or listtype == "JahrS" then
		ret = ret .. "border-bottom: 1pt solid white; width:10%' class='charts-th' | <span class='charts-hidm'>Position</span><span class='charts-monl'>#</span>"
	else
		ret = ret .. "text-align:left; width:15%' class='charts-trh' | Interpret "
		ret = ret .. "!! style='background-color:" .. colour2 .. "; border:none; text-align:left; font-style:italic; width:25%' class='charts-trh' | Titel"
		if listtype ~= "Alben" then
			ret = ret .. "<span style='font-size:smaller; font-style:normal;'><br />Autor(en)</span>"
		end
	end
	ret = ret .. "\n! style='background-color:" .. colour2 .. "; border:none;"
	if listtype == "Jahr" or listtype == "JahrA" then
		ret = ret .. "border-bottom: 1pt solid white; width:45%;' class='unsortable charts-th' | <span style='font-size:larger'>Alben</span>"
	elseif listtype == "JahrS" then
		ret = ret .. "border-bottom: 1pt solid white; width:45%;' class='unsortable charts-th' | <span style='font-size:larger'>Singles</span>"
	else
		ret = ret .. "text-align:left; width:40%;' class='unsortable charts-trh' | Zusätzliche Informationen"
		
		-- mobile table header
		ret = ret .. "\n|- style='background-color:" .. colour2 .. "'"
		ret = ret .. "\n! style='font-size:smaller; font-weight:normal; background-color:" .. colour2 .. "'"
		ret = ret .. " class='unsortable charts-monlc charts-th' | (Zeitraum,"
		if months then
			ret = ret .. " Monate"
		else
			ret = ret .. " Wochen"
		end
		ret = ret .. " auf Platz eins, Interpret, <i>Titel</i>, "
		if listtype ~= "Alben" then
			ret = ret .. "Autor[en], "
		end
		ret = ret .. "zusätzliche Informationen)"
		-- /
		
	end
	-- /
	
	-- content
	ret = ret .. "\n|- \n" .. (content or "") .. "\n|}"
	-- /
	
	-- navigation footer
	ret = ret .. "\n|- style='background-color:" .. colour1 .. ";' \n| style='line-height:1em;' | "
	if prevyear >= tonumber(firstyear) then
		ret = ret .. "[[" .. linkprev .. sectionlink .. "|← <br class='charts-monl' />" .. prevyear .. "]]"
	end
	ret = ret .. "\n| colspan='3' | &nbsp; \n| style='text-align:right;line-height:1em;' |"
	if tonumber(year) < currentyear then
		ret = ret .. "[[" .. linknext .. sectionlink .. "|<span class='charts-monl'>→<br /></span>" .. nextyear .. "<span class='charts-hidm'> →</span>]]"
	end
	-- /
	
	ret = ret .. "\n|}"

return ret

end


-- Nummer-eins-Hits Zeile - no. 1 table rows
p.no1tablerow = function (frame)
	local parameters = frame.args
	if not parameters.Chartein then parameters = mw.getCurrentFrame():getParent().args end
	
	local currentweek = mw.getContentLanguage():formatDate( 'W' )
	
	-- direct template parameters
	local chartentry = parameters.Chartein or tostring(currentweek - 1)
	if chartentry == "" then
		chartentry = nil
	end
	local chartexit = parameters.Chartaus or tostring(currentweek)
	if chartexit == "" then
		chartexit = nil
	end
	local yearturn = parameters.Jahr
	if yearturn == "" then
		yearturn = nil
	end
	local givenweeks = parameters.Wochen
	if givenweeks == "" then
		givenweeks = nil
	end
	local givenmonths = parameters.Monate
	if givenmonths == "" then
		givenmonths = nil
	end
	local total = parameters.Insges
	if total == "" then
		total = nil
	end
	local artist = parameters.Interpret
	if artist == "" then
		artist = nil
	end
	local title = parameters.Titel
	if title == "" then
		title = nil
	end
	local songwriters = parameters.Autor
	if songwriters == "" then
		songwriters = nil
	end
	local notes = parameters.Info
	if notes == "" then
		notes = nil
	end
	-- /

	-- derived parameters
	local pagename = mw.title.getCurrentTitle().text
	local year
	if string.match (pagename, ".+%(%d%d%d%d%)") then
		year = string.match (pagename, ".+%((%d%d%d%d)%)")
	else
		year = os.date( "%Y" )
	end
	local chartentryyear
	if string.match (chartentry, "%d%d%d%d") then
		chartentryyear = string.match (chartentry, "(%d%d%d%d)")
	end
	local chartexityear = string.match (chartexit, "(%d%d%d%d)")
	if string.match (chartexit, "%d%d%d%d") then
		chartexityear = string.match (chartexit, "(%d%d%d%d)")
	end
	-- /
	
	-- service links
	local slgiven = "<span style='display:none'>[[Template:Nummer-eins-Hits/Wartung/feste Dauer]]</span>"
	local slmonths = "<span style='display:none'>[[Template:Nummer-eins-Hits/Wartung/Monate]]</span>"
	local slerrordate = "<span style='display:none'>[[Template:Nummer-eins-Hits/Wartung/Datumsfehler]]</span>"
	-- /
	
	-- date formats
	local entrydateview
	local entrydateweek
	local entrydatemonth
	local sortdate
	if #chartentry > 2 then
		local entrydate = DateTime (chartentry)
		if type (entrydate) == "string" or type (entrydate) == "boolean" then
			return "<span class='error'>Parameter Chartein: falsches Format</span>" .. slerrordate
		end
		entrydateview = entrydate:format ("T._Monat JJJJ")
		sortdate = entrydate:format ("ISO")
		entrydateweek = entrydate:format ("W")
		entrydatemonth = entrydate:format ("m")
	else
		entrydateview = chartentry .. "."
		sortdate = chartentry
		entrydateweek = chartentry
	end
	
	local exitdateview
	local exitdateweek
	local exitdatemonth
	if #chartexit > 2 then
		local exitdate = DateTime (chartexit)
		if type (exitdate) == "string" or type (exitdate) == "boolean" then
			return "<span class='error'>Parameter Chartaus: falsches Format</span>" .. slerrordate
		end
		exitdateview = exitdate:format ("T._Monat JJJJ")
		local exitdate1 = exitdate + "1 day"
		exitdateweek = exitdate1:format ("W")
		exitdatemonth = exitdate:format ("m")
	else
		exitdateview = chartexit .. ".&nbsp;Woche"
		exitdateweek = chartexit + 1
	end

	-- auto-calculate week and month number
	local weeks = (exitdateweek - entrydateweek)
	local months
	if #chartentry > 2 and #chartexit > 2 then
		months = (exitdatemonth - entrydatemonth) + 1
		if months < 0 then
			months = months + 12
		end
	end
	local year1 = year
	if yearturn == "-1" then
		year1 = year - 1
	end
	if chartentryyear then
		year1 = chartentryyear
		if chartentryyear == chartexityear then
			if tonumber(exitdatemonth) then
				if tonumber(exitdatemonth) < 10 then
					year1 = year1 - 1
				end
			end
		end
	end
	local endweekdate = year1 .. "-12-28"
	local endweek = DateTime (endweekdate)
	local weeksyear = endweek:format ("W")
	if weeks < 0 then
		weeks = weeks + weeksyear
	end
	if weeks == 0 then
		weeks = 1
	end

	-- build table row
	local ret = "\n|- class='newno1tablerow' style='padding-top:5px; border:none; margin:0;' "
	
	-- date
	ret = ret .. "\n| style='border:none;' data-sort-value='" .. sortdate .. "'|" .. entrydateview
	if #chartentry <= 2 and #chartexit <= 2 then
		if tonumber(chartexit) < tonumber(chartentry) then
			if yearturn == "-1" then
				ret = ret .. "&nbsp;Woche " .. (year -1) .. "&nbsp;&ndash; " .. exitdateview .. " " .. (year)
			else
				ret = ret .. "&nbsp;Woche " .. year .. "&nbsp;&ndash; " .. exitdateview .. " " .. (year +1)
			end
		elseif chartentry == chartexit then
			ret = ret .. "&nbsp;Woche"
		else
			ret = ret .. "&ndash;" .. exitdateview
		end
	elseif entrydateview ~= exitdateview then
		if #chartentry <= 2 then
			ret = ret .. " Woche"
		end
		ret = ret .. "&nbsp;&ndash; " .. exitdateview
	end
	ret = ret .. "<br /><span style='font-size:smaller'>"
	
	local monthview
	if (not string.match (entrydateview, "%.") and not givenweeks) or givenmonths then
		monthview = true
	end
	
	if not monthview then
		ret = ret .. (givenweeks or weeks or "&hellip;") .. "&nbsp;Woche"
		if givenweeks then
			if givenweeks ~= "1" then
				ret = ret .. "n"
			end
		else
			if weeks ~= 1 then
				ret = ret .. "n"
			end
		end
	else
		ret = ret .. (givenmonths or months or "&hellip;") .. "&nbsp;Monat"
		if givenmonths then
			if givenmonths ~= "1" and givenmonths ~= "½" then
				ret = ret .. "e"
			end
		else
			if months ~= 1 and months ~= "½" then
				ret = ret .. "e"
			end
		end
	end
	ret = ret .. "</span>"
	-- /
	
	-- total weeks/months
	local totaldisplay
	local mobiletotal
	if monthview then
		totaldisplay = total or givenmonths or months
		if totaldisplay ~= months then
			mobiletotal = true
		end
	else
		totaldisplay = total or givenweeks or weeks
		if totaldisplay ~= weeks then
			mobiletotal = true
		end
	end
	if mobiletotal then
		ret = ret .. "<span style='font-size:smaller;' class='charts-monl'> (insgesamt " .. totaldisplay .. ")</span>"
	end
	ret = ret .. "\n| style='text-align:center; border:none;' class='charts-hidm' |" .. totaldisplay
	-- /
	
	ret = ret .. "\n| style='border:none;' "
	if artist then
		if string.match(artist, "data%-sort%-value") then
			ret = ret .. artist
		else
			ret = ret .. "| " .. artist
		end
	else
		ret = ret .. "| Interpret"
	end
	
	ret = ret .. "\n| style='border:none; font-style:italic;' | " .. (title or "Titel")
	
	if songwriters then
		ret = ret .. "<br /><span style='font-style:normal;font-size:smaller;'>" .. songwriters .. "</span>"
	end
	
	ret = ret .. "\n|"
	if not notes then ret = ret .. " class='charts-hidm'" end
	ret = ret .. " style='border:none;' | " .. (notes or "&ndash;")
	
	-- create service links
	if givenweeks or givenmonths then
		ret = ret .. slgiven
	elseif monthview then
		ret = ret .. slmonths
	end
	-- /
	
	return ret
end


-- Jahreshitparaden Zeile - year-end chart table row
p.yearendrow = function (frame, half)
	local parameters = frame.args
	if not parameters.Position then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local position = parameters.Position
	
	local single = parameters.Single
	if single == "" then
		single = false
	end
	local album = parameters.Album
	if album == "" then
		album = false
	end
	local singleartist = parameters.InterpretS
	if singleartist == "" then
		singleartist = false
	end
	local albumartist = parameters.InterpretA
	if albumartist == "" then
		albumartist = false
	end
	local songwriter = parameters.Autor
	if songwriter == "" then
		songwriter = false
	end
	-- /
	
	local ret = "|- class='newno1tablerow' style='padding-top:5px; border:none; margin:0;'"
	if not half then
		ret = ret .. "\n| style='text-align:center; border:none; margin:0; width:45%'|"
		ret = ret .. "<i>" .. (single or "&hellip;") .. "</i>"
		if singleartist then
			ret = ret .. "<br />" .. singleartist
		end
		if songwriter then
			ret = ret .. "<br /><span style='font-size:smaller'>" .. songwriter .. "</span>"
		end
	end
	ret = ret .. "\n| style='text-align:center; font-size:larger; font-weight:bold; border:none; margin:0; width:10%'|" .. (position or "#")
	ret = ret .. "\n| style='text-align:center; border:none; margin:0; width:45%'|"
	ret = ret .. "<i>"
	if half then
		ret = ret .. (album or single or "&hellip;") 
	else
		ret = ret .. (album or "&hellip;")
	end
	ret = ret .. "</i>"
	if albumartist then
		ret = ret .. "<br />" .. albumartist
	elseif half then
		if singleartist then
			ret = ret .. "<br />" .. singleartist
		end
		if songwriter then
			ret = ret .. "<br /><span style='font-size:smaller'>" .. songwriter .. "</span>"
		end
	end
	
	return ret
	
end


-- Jahreshitparade Zeile - year-end chart table row one-col
p.yearendrowhalf = function (frame)
	local parameters = frame.args
	if not parameters.Position then parameters = mw.getCurrentFrame():getParent().args end
	
	local half = true
	
	return p.yearendrow( frame, half )

end


return p